commit
b581327c71
@ -27,8 +27,8 @@ Easiest way to install the lastest required packages on Linux is via nvm.
|
||||
``` source ~/.profile ``` (For Debian based distro) <br/>
|
||||
``` source ~/.bashrc ``` (For Fedora / CentOS) <br/>
|
||||
``` nvm ls-remote ``` (Fetch list of available versions) <br/>
|
||||
``` nvm install v18.14.0 ``` (LTS: Hydrogen supported by Electron) <br/>
|
||||
``` npm --location=global install npm@9.7.2 ``` <br/>
|
||||
``` nvm install v18.15.0 ``` (LTS: Hydrogen supported by Electron) <br/>
|
||||
``` npm --location=global install npm@9.8.1 ``` <br/>
|
||||
|
||||
Adding via binary package mirror will only work if you have set the package path. You can do a node or java build via ports instead by downloading ports with portsnap fetch method.
|
||||
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "Prägung",
|
||||
"wp2": "Nicht am Prägen",
|
||||
"wp3": "Kerninformationen",
|
||||
"wp4": "Synchronisiert"
|
||||
"wp4": "Synchronisiert",
|
||||
"wp5": "Synchronisierungsstatus"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Ja",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "Acuñación",
|
||||
"wp2": "Sin acuñar",
|
||||
"wp3": "Información básica",
|
||||
"wp4": "Sincronizado"
|
||||
"wp4": "Sincronizado",
|
||||
"wp5": "Estado de sincronización"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Sí",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "Monnaie",
|
||||
"wp2": "Pas de frappe",
|
||||
"wp3": "Informations de base",
|
||||
"wp4": "Synchronisé"
|
||||
"wp4": "Synchronisé",
|
||||
"wp5": "État de la synchronisation"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Oui",
|
||||
|
@ -215,7 +215,8 @@
|
||||
"wp1": "खनन",
|
||||
"wp2": "नॉट मिंटिंग",
|
||||
"wp3": "मुख्य जानकारी",
|
||||
"wp4": "सिंक्रोनाइज़्ड"
|
||||
"wp4": "सिंक्रोनाइज़्ड",
|
||||
"wp5": "सिंक स्थिति"
|
||||
},
|
||||
"general": {
|
||||
"yes": "हाँ",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "Kovanje",
|
||||
"wp2": "Nije kovano",
|
||||
"wp3": "Osnovne informacije",
|
||||
"wp4": "Sinkronizirano"
|
||||
"wp4": "Sinkronizirano",
|
||||
"wp5": "Status sinkronizacije"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Da",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "verés",
|
||||
"wp2": "Nem pénzverés",
|
||||
"wp3": "Alapinformációk",
|
||||
"wp4": "Szinkronizált"
|
||||
"wp4": "Szinkronizált",
|
||||
"wp5": "Szinkronizálás állapota"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Igen",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "Conio",
|
||||
"wp2": "Non conio",
|
||||
"wp3": "Informazioni principali",
|
||||
"wp4": "Sincronizzato"
|
||||
"wp4": "Sincronizzato",
|
||||
"wp5": "Stato sincronizzazione"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Yes",
|
||||
|
@ -216,7 +216,8 @@
|
||||
"wp1": "ミント",
|
||||
"wp2": "鋳造しない",
|
||||
"wp3": "コア情報",
|
||||
"wp4": "同期済み"
|
||||
"wp4": "同期済み",
|
||||
"wp5": "同期ステータス"
|
||||
},
|
||||
"general": {
|
||||
"yes": "はい",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "조폐",
|
||||
"wp2": "조폐되지 않음",
|
||||
"wp3": "핵심 정보",
|
||||
"wp4": "동기화됨"
|
||||
"wp4": "동기화됨",
|
||||
"wp5": "동기화 상태"
|
||||
},
|
||||
"general": {
|
||||
"yes": "예",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "Minting",
|
||||
"wp2": "Ikke preging",
|
||||
"wp3": "Kjerneinformasjon",
|
||||
"wp4": "Synkronisert"
|
||||
"wp4": "Synkronisert",
|
||||
"wp5": "Synkroniseringsstatus"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Ja",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "Bicie",
|
||||
"wp2": "Nie bije",
|
||||
"wp3": "Podstawowe informacje",
|
||||
"wp4": "Zsynchronizowany"
|
||||
"wp4": "Zsynchronizowany",
|
||||
"wp5": "Stan synchronizacji"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Tak",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "Criação",
|
||||
"wp2": "Não está cunhando",
|
||||
"wp3": "Informações essenciais",
|
||||
"wp4": "Sincronizado"
|
||||
"wp4": "Sincronizado",
|
||||
"wp5": "Status da sincronização"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Sim",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "Battering",
|
||||
"wp2": "Nu se bate",
|
||||
"wp3": "Informații de bază",
|
||||
"wp4": "Sincronizat"
|
||||
"wp4": "Sincronizat",
|
||||
"wp5": "Stare sincronizare"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Da",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "Kovanje",
|
||||
"wp2": "Ne kuje",
|
||||
"wp3": "Osnovne informacije",
|
||||
"wp4": "Sinhronizovano"
|
||||
"wp4": "Sinhronizovano",
|
||||
"wp5": "Status sinhronizacije"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Da",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "Чеканка",
|
||||
"wp2": "Не чеканить",
|
||||
"wp3": "Основная информация",
|
||||
"wp4": "Синхронизировано"
|
||||
"wp4": "Синхронизировано",
|
||||
"wp5": "Статус синхронизации"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Да",
|
||||
|
@ -219,7 +219,8 @@
|
||||
"wp1": "Minting",
|
||||
"wp2": "Not Minting",
|
||||
"wp3": "Core Information",
|
||||
"wp4": "Synchronized"
|
||||
"wp4": "Synchronized",
|
||||
"wp5": "Sync Status"
|
||||
},
|
||||
"general": {
|
||||
"yes": "Yes",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "铸造",
|
||||
"wp2": "不铸造",
|
||||
"wp3": "核心信息",
|
||||
"wp4": "已同步"
|
||||
"wp4": "已同步",
|
||||
"wp5": "同步状态"
|
||||
},
|
||||
"general": {
|
||||
"yes": "是",
|
||||
|
@ -214,7 +214,8 @@
|
||||
"wp1": "鑄造",
|
||||
"wp2": "不鑄造",
|
||||
"wp3": "核心信息",
|
||||
"wp4": "已同步"
|
||||
"wp4": "已同步",
|
||||
"wp5": "同步狀態"
|
||||
},
|
||||
"general": {
|
||||
"yes": "是",
|
||||
|
@ -7,6 +7,7 @@ import { get, translate, translateUnsafeHTML } from 'lit-translate'
|
||||
import localForage from 'localforage'
|
||||
import { encryptData, decryptData } from '../lockScreen.js'
|
||||
import { setChatLastSeen } from '../redux/app/app-actions.js'
|
||||
import isElectron from 'is-electron'
|
||||
|
||||
const chatLastSeen = localForage.createInstance({
|
||||
name: "chat-last-seen",
|
||||
@ -427,7 +428,7 @@ class AppView extends connect(store)(LitElement) {
|
||||
constructor() {
|
||||
super()
|
||||
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
|
||||
this.urls = [];
|
||||
this.urls = []
|
||||
this.nodeType = ''
|
||||
this.addressInfo = {}
|
||||
this.getAllBalancesLoading = false
|
||||
@ -649,6 +650,8 @@ class AppView extends connect(store)(LitElement) {
|
||||
addTradeBotRoutes(parentEpml)
|
||||
parentEpml.imReady()
|
||||
|
||||
this.clearTheCache()
|
||||
|
||||
this.helperMessage = this.renderHelperPass()
|
||||
|
||||
this.salt = ''
|
||||
@ -1581,14 +1584,14 @@ class AppView extends connect(store)(LitElement) {
|
||||
}
|
||||
|
||||
const getChatLastSeen = async () => {
|
||||
let items = [];
|
||||
let items = []
|
||||
|
||||
await chatLastSeen.iterate(function (value, key, iterationNumber) {
|
||||
|
||||
items.push({ key, timestamp: value });
|
||||
items.push({ key, timestamp: value })
|
||||
})
|
||||
|
||||
store.dispatch(setChatLastSeen(items))
|
||||
return items;
|
||||
return items
|
||||
}
|
||||
|
||||
await getOpenTradesBTC()
|
||||
@ -1603,14 +1606,26 @@ class AppView extends connect(store)(LitElement) {
|
||||
await appDelay(1000)
|
||||
await getOpenTradesARRR()
|
||||
await getChatLastSeen()
|
||||
setInterval(() => {
|
||||
this.clearTheCache()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
shBalanceTicker() {
|
||||
const targetDiv = this.shadowRoot.getElementById("theTicker")
|
||||
if (targetDiv.style.display !== "none") {
|
||||
targetDiv.style.display = "none";
|
||||
targetDiv.style.display = "none"
|
||||
} else {
|
||||
targetDiv.style.display = "inline";
|
||||
targetDiv.style.display = "inline"
|
||||
}
|
||||
}
|
||||
|
||||
clearTheCache() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearMyCache()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
|
54
electron.js
54
electron.js
@ -1,16 +1,17 @@
|
||||
const {
|
||||
app,
|
||||
BrowserWindow,
|
||||
ipcMain,
|
||||
ipcRenderer,
|
||||
Menu,
|
||||
Notification,
|
||||
Tray,
|
||||
nativeImage,
|
||||
dialog,
|
||||
webContents,
|
||||
nativeTheme,
|
||||
crashReporter
|
||||
app,
|
||||
BrowserWindow,
|
||||
ipcMain,
|
||||
ipcRenderer,
|
||||
Menu,
|
||||
Notification,
|
||||
Tray,
|
||||
nativeImage,
|
||||
dialog,
|
||||
webContents,
|
||||
nativeTheme,
|
||||
crashReporter,
|
||||
webFrame
|
||||
} = require('electron')
|
||||
|
||||
const { autoUpdater } = require('electron-updater')
|
||||
@ -40,19 +41,16 @@ crashReporter.start({
|
||||
uploadToServer: false
|
||||
})
|
||||
|
||||
if (myMemory > 16000000000) {
|
||||
app.commandLine.appendSwitch('js-flags', '--max-old-space-size=8192')
|
||||
log.info("Memory Size Is 16GB Using JS Memory Heap Size 8GB")
|
||||
} else if (myMemory > 12000000000) {
|
||||
app.commandLine.appendSwitch('js-flags', '--max-old-space-size=6144')
|
||||
log.info("Memory Size Is 12GB Using JS Memory Heap Size 6GB")
|
||||
} else if (myMemory > 7000000000) {
|
||||
app.commandLine.appendSwitch('js-flags', '--max-old-space-size=4096')
|
||||
log.info("Memory Size Is 8GB Using JS Memory Heap Size 4GB")
|
||||
} else {
|
||||
app.commandLine.appendSwitch('js-flags', '--max-old-space-size=2048')
|
||||
log.info("Memory Size Is 4GB Using JS Memory Heap Size 2GB")
|
||||
}
|
||||
app.commandLine.appendSwitch('js-flags', '--max-executable-size=192 --max-old-space-size=1024 --max-semi-space-size=2')
|
||||
|
||||
setInterval (function() {
|
||||
let mu = process.memoryUsage()
|
||||
log.info('heapTotal:', mu.heapTotal, 'heapUsed:', mu.heapUsed);
|
||||
if (mu.heapUsed > 1024 * 1024 * 1024) {
|
||||
log.info('Taking out the garbage')
|
||||
global.gc()
|
||||
}
|
||||
}, 1000 * 120)
|
||||
|
||||
if (process.arch === 'arm') {
|
||||
app.disableHardwareAcceleration()
|
||||
@ -1031,6 +1029,12 @@ if (!isLock) {
|
||||
}
|
||||
})
|
||||
})
|
||||
ipcMain.on('clear-all-cache', (event) => {
|
||||
const theWindows = BrowserWindow.getAllWindows()[0]
|
||||
const ses = theWindows.webContents.session
|
||||
console.clear()
|
||||
ses.clearCache()
|
||||
})
|
||||
ipcMain.on('check-for-update', (event) => {
|
||||
const check = new Notification({
|
||||
title: i18n.__("electron_translate_43"),
|
||||
|
@ -1,8 +1,12 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
const { contextBridge, ipcRenderer, webFrame } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
setStartCore: () => ipcRenderer.send('set-start-core'),
|
||||
checkForUpdate: () => ipcRenderer.send('check-for-update'),
|
||||
showMyMenu: () => ipcRenderer.send('show-my-menu'),
|
||||
focusApp: () => ipcRenderer.send('focus-app'),
|
||||
clearMyCache: () => ipcRenderer.send('clear-all-cache'),
|
||||
clearCache() {
|
||||
webFrame.clearCache()
|
||||
},
|
||||
})
|
2556
package-lock.json
generated
2556
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
46
package.json
46
package.json
@ -51,29 +51,29 @@
|
||||
"prosemirror-gapcursor": "1.3.2",
|
||||
"prosemirror-history": "1.3.2",
|
||||
"prosemirror-keymap": "1.2.2",
|
||||
"prosemirror-model": "1.19.2",
|
||||
"prosemirror-model": "1.19.3",
|
||||
"prosemirror-schema-list": "1.3.0",
|
||||
"prosemirror-state": "1.4.3",
|
||||
"prosemirror-transform": "1.7.3",
|
||||
"prosemirror-view": "1.31.5",
|
||||
"sass": "1.63.6",
|
||||
"prosemirror-transform": "1.7.4",
|
||||
"prosemirror-view": "1.31.7",
|
||||
"sass": "1.64.1",
|
||||
"short-unique-id": "4.4.4",
|
||||
"@hapi/hapi": "21.3.2",
|
||||
"@hapi/inert": "7.1.0",
|
||||
"@lit-labs/motion": "1.0.3",
|
||||
"@tiptap/pm": "2.0.3",
|
||||
"@tiptap/core": "2.0.3",
|
||||
"@tiptap/extension-highlight": "2.0.3",
|
||||
"@tiptap/extension-image": "2.0.3",
|
||||
"@tiptap/extension-placeholder": "2.0.3",
|
||||
"@tiptap/extension-underline": "2.0.3",
|
||||
"@tiptap/html": "2.0.3",
|
||||
"@tiptap/starter-kit": "2.0.3"
|
||||
"@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": {
|
||||
"axios": "1.4.0",
|
||||
"electron": "25.3.0",
|
||||
"electron-builder": "24.4.0",
|
||||
"electron": "25.3.2",
|
||||
"electron-builder": "24.6.3",
|
||||
"electron-packager": "17.1.1",
|
||||
"epml": "0.3.3",
|
||||
"file-saver": "2.0.5",
|
||||
@ -86,7 +86,7 @@
|
||||
"passive-events-support": "1.1.0",
|
||||
"redux": "4.2.1",
|
||||
"redux-thunk": "2.4.2",
|
||||
"rollup": "3.26.2",
|
||||
"rollup": "3.27.0",
|
||||
"rollup-plugin-node-globals": "1.4.0",
|
||||
"rollup-plugin-progress": "1.1.2",
|
||||
"rollup-plugin-scss": "3.0.0",
|
||||
@ -130,19 +130,19 @@
|
||||
"@qortal/rollup-plugin-web-worker-loader": "1.6.4",
|
||||
"@rollup/plugin-alias": "5.0.0",
|
||||
"@rollup/plugin-babel": "6.0.3",
|
||||
"@rollup/plugin-commonjs": "25.0.2",
|
||||
"@rollup/plugin-commonjs": "25.0.3",
|
||||
"@rollup/plugin-node-resolve": "15.1.0",
|
||||
"@rollup/plugin-replace": "5.0.2",
|
||||
"@rollup/plugin-terser": "0.4.3",
|
||||
"@vaadin/avatar": "24.1.3",
|
||||
"@vaadin/button": "24.1.3",
|
||||
"@vaadin/grid": "24.1.3",
|
||||
"@vaadin/icons": "24.1.3",
|
||||
"@vaadin/password-field": "24.1.3",
|
||||
"@vaadin/tooltip": "24.1.3",
|
||||
"@vaadin/avatar": "24.1.4",
|
||||
"@vaadin/button": "24.1.4",
|
||||
"@vaadin/grid": "24.1.4",
|
||||
"@vaadin/icons": "24.1.4",
|
||||
"@vaadin/password-field": "24.1.4",
|
||||
"@vaadin/tooltip": "24.1.4",
|
||||
"@zip.js/zip.js": "2.7.20"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.14.0"
|
||||
"node": ">=18.15.0"
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,18 @@ class BecomeMinter extends LitElement {
|
||||
window.parent.electronAPI.showMyMenu()
|
||||
})
|
||||
}
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
async getRewardShareRelationship(recipientAddress) {
|
||||
|
@ -1,19 +1,15 @@
|
||||
import { LitElement, html } from 'lit';
|
||||
import { Epml } from '../../../../epml.js';
|
||||
import '../../components/ButtonIconCopy.js';
|
||||
import { use, translate, registerTranslateConfig } from 'lit-translate';
|
||||
import { LitElement, html } from 'lit'
|
||||
import { Epml } from '../../../../epml.js'
|
||||
import '../../components/ButtonIconCopy.js'
|
||||
import { use, get, translate, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
registerTranslateConfig({
|
||||
loader: (lang) => fetch(`/language/${lang}.json`).then((res) => res.json()),
|
||||
});
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-textfield'
|
||||
import '@vaadin/button'
|
||||
import { pageStyles } from '../become-minter-css.src.js'
|
||||
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js';
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-textfield';
|
||||
import '@vaadin/button';
|
||||
import { pageStyles } from '../become-minter-css.src.js';
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class NotSponsored extends LitElement {
|
||||
static properties = {
|
||||
@ -27,18 +23,18 @@ class NotSponsored extends LitElement {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.isLoadingSponsorshipKeySubmit = false;
|
||||
this.sponsorshipKeyValue = '';
|
||||
this.addMintingAccountMessage = '';
|
||||
this.atMount = () => {};
|
||||
this.isLoadingSponsorshipKeySubmit = false
|
||||
this.sponsorshipKeyValue = ''
|
||||
this.addMintingAccountMessage = ''
|
||||
this.atMount = () => {}
|
||||
}
|
||||
|
||||
renderErr1Text() {
|
||||
return html`${translate('nodepage.nchange27')}`;
|
||||
return html`${translate('nodepage.nchange27')}`
|
||||
}
|
||||
|
||||
renderErr2Text() {
|
||||
return html`${translate('nodepage.nchange28')}`;
|
||||
return html`${translate('nodepage.nchange28')}`
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
@ -46,13 +42,13 @@ class NotSponsored extends LitElement {
|
||||
window.parent.reduxStore.getState().app.nodeConfig.knownNodes[
|
||||
window.parent.reduxStore.getState().app.nodeConfig.node
|
||||
];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
let apiKey = myNode.apiKey
|
||||
return apiKey
|
||||
}
|
||||
|
||||
addMintingAccount(e) {
|
||||
this.isLoadingSponsorshipKeySubmit = true;
|
||||
this.addMintingAccountMessage = 'Loading...';
|
||||
this.isLoadingSponsorshipKeySubmit = true
|
||||
this.addMintingAccountMessage = 'Loading...'
|
||||
|
||||
parentEpml
|
||||
.request('apiCall', {
|
||||
@ -63,20 +59,20 @@ class NotSponsored extends LitElement {
|
||||
.then((res) => {
|
||||
if (res === true) {
|
||||
// refetch data
|
||||
this.atMount();
|
||||
this.sponsorshipKeyValue = '';
|
||||
this.addMintingAccountMessage = this.renderErr1Text();
|
||||
this.isLoadingSponsorshipKeySubmit = false;
|
||||
this.atMount()
|
||||
this.sponsorshipKeyValue = ''
|
||||
this.addMintingAccountMessage = this.renderErr1Text()
|
||||
this.isLoadingSponsorshipKeySubmit = false
|
||||
} else {
|
||||
this.sponsorshipKeyValue = '';
|
||||
this.addMintingAccountMessage = this.renderErr2Text();
|
||||
this.isLoadingSponsorshipKeySubmit = false;
|
||||
this.addMintingAccountMessage = this.renderErr2Text()
|
||||
this.isLoadingSponsorshipKeySubmit = false
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
inputHandler(e) {
|
||||
this.sponsorshipKeyValue = e.target.value;
|
||||
this.sponsorshipKeyValue = e.target.value
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -130,8 +126,8 @@ class NotSponsored extends LitElement {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('not-sponsored', NotSponsored);
|
||||
window.customElements.define('not-sponsored', NotSponsored)
|
||||
|
@ -1,18 +1,14 @@
|
||||
import { LitElement, html } from 'lit';
|
||||
import { Epml } from '../../../../epml.js';
|
||||
import '../../components/ButtonIconCopy.js';
|
||||
import { use, translate, registerTranslateConfig } from 'lit-translate';
|
||||
import { LitElement, html } from 'lit'
|
||||
import { Epml } from '../../../../epml.js'
|
||||
import '../../components/ButtonIconCopy.js'
|
||||
import { use, get, translate, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
registerTranslateConfig({
|
||||
loader: (lang) => fetch(`/language/${lang}.json`).then((res) => res.json()),
|
||||
});
|
||||
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js';
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-textfield';
|
||||
import '@vaadin/button';
|
||||
import { blocksNeed } from '../../../utils/blocks-needed.js';
|
||||
import { pageStyles } from '../become-minter-css.src.js';
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-textfield'
|
||||
import '@vaadin/button'
|
||||
import { blocksNeed } from '../../../utils/blocks-needed.js'
|
||||
import { pageStyles } from '../become-minter-css.src.js'
|
||||
|
||||
class YesSponsored extends LitElement {
|
||||
static get properties() {
|
||||
@ -24,14 +20,13 @@ class YesSponsored extends LitElement {
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.addressInfo = {};
|
||||
this.rewardSharePublicKey = '';
|
||||
super()
|
||||
this.addressInfo = {}
|
||||
this.rewardSharePublicKey = ''
|
||||
this.isMinting = false
|
||||
}
|
||||
|
||||
static styles = [pageStyles];
|
||||
static styles = [pageStyles]
|
||||
|
||||
_levelUpBlocks() {
|
||||
let countBlocksString = (
|
||||
@ -39,7 +34,7 @@ class YesSponsored extends LitElement {
|
||||
(this.addressInfo?.blocksMinted +
|
||||
this.addressInfo?.blocksMintedAdjustment)
|
||||
).toString();
|
||||
return countBlocksString;
|
||||
return countBlocksString
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -107,8 +102,8 @@ class YesSponsored extends LitElement {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('yes-sponsored', YesSponsored);
|
||||
window.customElements.define('yes-sponsored', YesSponsored)
|
||||
|
@ -5,12 +5,12 @@ import * as zip from '@zip.js/zip.js';
|
||||
import '@material/mwc-icon';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
import {publishData} from '../../../utils/publish-image.js';
|
||||
import {translate, get} from 'lit-translate';
|
||||
import {gifExplorerStyles} from './ChatGifs-css.js';
|
||||
import { bytesToMegabytes } from '../../../utils/bytesToMegabytes.js';
|
||||
import './ChatGifsExplore.js';
|
||||
import '../ImageComponent.js';
|
||||
import '@vaadin/tooltip';
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
const parentEpml = new Epml({type: 'WINDOW', source: window.parent});
|
||||
|
||||
@ -993,4 +993,4 @@ setOpenGifModal: { attribute: false }
|
||||
|
||||
}
|
||||
|
||||
window.customElements.define('chat-gifs', ChatGifs);
|
||||
window.customElements.define('chat-gifs', ChatGifs)
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { Epml } from '../../../../epml.js';
|
||||
import { chatGifsExploreStyles } from './ChatGifsExplore-css.js';
|
||||
import { translate, get } from 'lit-translate';
|
||||
import '@material/mwc-icon';
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { Epml } from '../../../../epml.js'
|
||||
import { chatGifsExploreStyles } from './ChatGifsExplore-css.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
import '@material/mwc-icon'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
|
||||
|
||||
@ -69,9 +69,9 @@ class ChatGifsExplore extends LitElement {
|
||||
this.elementObserver();
|
||||
}
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
let apiKey = myNode.apiKey
|
||||
return apiKey
|
||||
}
|
||||
|
||||
async searchCollections() {
|
||||
@ -169,4 +169,4 @@ class ChatGifsExplore extends LitElement {
|
||||
|
||||
}
|
||||
|
||||
window.customElements.define('chat-gifs-explore', ChatGifsExplore);
|
||||
window.customElements.define('chat-gifs-explore', ChatGifsExplore)
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { LitElement, html, css } from "lit"
|
||||
import { render } from "lit/html.js"
|
||||
import { get, translate } from "lit-translate"
|
||||
import { Epml } from "../../../epml"
|
||||
import snackbar from "./snackbar.js"
|
||||
import "@material/mwc-button"
|
||||
@ -8,6 +7,7 @@ import "@material/mwc-dialog"
|
||||
import "@polymer/paper-spinner/paper-spinner-lite.js"
|
||||
import "@material/mwc-icon"
|
||||
import "./WrapperModal"
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
const parentEpml = new Epml({ type: "WINDOW", source: window.parent })
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { get, translate } from 'lit-translate';
|
||||
import { Epml } from '../../../epml';
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml'
|
||||
import snackbar from './snackbar.js'
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-dialog';
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@material/mwc-icon';
|
||||
import './WrapperModal';
|
||||
import '@material/mwc-icon'
|
||||
import './WrapperModal'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
@ -25,7 +25,7 @@ class ChatGroupSettings extends LitElement {
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
super()
|
||||
this.isLoading = false;
|
||||
this.isOpenLeaveModal = false
|
||||
this.leaveGroupObj = {}
|
||||
|
@ -1,19 +1,19 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { get, translate } from 'lit-translate';
|
||||
import { Epml } from '../../../epml';
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml'
|
||||
import snackbar from './snackbar.js'
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-dialog';
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@material/mwc-icon';
|
||||
import './WrapperModal';
|
||||
import '@material/mwc-icon'
|
||||
import './WrapperModal'
|
||||
import '@vaadin/tabs'
|
||||
import '@vaadin/tabs/theme/material/vaadin-tabs.js';
|
||||
import '@vaadin/avatar';
|
||||
import '@vaadin/grid';
|
||||
import '@vaadin/grid/vaadin-grid-filter-column.js';
|
||||
import { columnBodyRenderer } from '@vaadin/grid/lit.js';
|
||||
import '@vaadin/tabs/theme/material/vaadin-tabs.js'
|
||||
import '@vaadin/avatar'
|
||||
import '@vaadin/grid'
|
||||
import '@vaadin/grid/vaadin-grid-filter-column.js'
|
||||
import { columnBodyRenderer } from '@vaadin/grid/lit.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
|
@ -1,18 +1,20 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
import localForage from "localforage";
|
||||
import { translate} from 'lit-translate';
|
||||
|
||||
import localForage from "localforage"
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
import '@material/mwc-icon'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
const chatLastSeen = localForage.createInstance({
|
||||
name: "chat-last-seen",
|
||||
});
|
||||
})
|
||||
|
||||
class ChatHead extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
theme: { type: String, reflect: true },
|
||||
selectedAddress: { type: Object },
|
||||
config: { type: Object },
|
||||
chatInfo: { type: Object },
|
||||
@ -53,10 +55,7 @@ class ChatHead extends LitElement {
|
||||
color: var(--chat-group);
|
||||
}
|
||||
|
||||
|
||||
|
||||
.about {
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@ -109,12 +108,13 @@ class ChatHead extends LitElement {
|
||||
this.imageFetches = 0
|
||||
this.lastReadMessageTimestamp = 0
|
||||
this.loggedInAddress = window.parent.reduxStore.getState().app.selectedAddress.address
|
||||
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
|
||||
}
|
||||
|
||||
createImage(imageUrl) {
|
||||
const imageHTMLRes = new Image();
|
||||
imageHTMLRes.src = imageUrl;
|
||||
imageHTMLRes.style= "width:40px; height:40px; float: left; border-radius:50%";
|
||||
const imageHTMLRes = new Image()
|
||||
imageHTMLRes.src = imageUrl
|
||||
imageHTMLRes.style= "width:40px; height:40px; float: left; border-radius:50%"
|
||||
imageHTMLRes.onclick= () => {
|
||||
this.openDialogImage = true;
|
||||
}
|
||||
@ -124,29 +124,25 @@ class ChatHead extends LitElement {
|
||||
imageHTMLRes.onerror = () => {
|
||||
if (this.imageFetches < 4) {
|
||||
setTimeout(() => {
|
||||
this.imageFetches = this.imageFetches + 1;
|
||||
imageHTMLRes.src = imageUrl;
|
||||
}, 750);
|
||||
this.imageFetches = this.imageFetches + 1
|
||||
imageHTMLRes.src = imageUrl
|
||||
}, 750)
|
||||
} else {
|
||||
|
||||
|
||||
this.isImageLoaded = false
|
||||
}
|
||||
};
|
||||
return imageHTMLRes;
|
||||
return imageHTMLRes
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
let avatarImg = '';
|
||||
let avatarImg = ''
|
||||
let backupAvatarImg = ''
|
||||
let isUnread = false
|
||||
|
||||
if(this.chatInfo.name){
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
const avatarUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${this.chatInfo.name}/qortal_avatar?async=true&apiKey=${myNode.apiKey}`;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
const avatarUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${this.chatInfo.name}/qortal_avatar?async=true&apiKey=${myNode.apiKey}`
|
||||
avatarImg= this.createImage(avatarUrl)
|
||||
}
|
||||
|
||||
@ -189,6 +185,19 @@ class ChatHead extends LitElement {
|
||||
}
|
||||
|
||||
async firstUpdated() {
|
||||
this.changeTheme()
|
||||
|
||||
window.addEventListener('storage', () => {
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark'
|
||||
} else {
|
||||
this.theme = 'light'
|
||||
}
|
||||
document.querySelector('html').setAttribute('theme', this.theme)
|
||||
})
|
||||
|
||||
let configLoaded = false
|
||||
this.lastReadMessageTimestamp = await chatLastSeen.getItem(this.chatInfo.url) || 0
|
||||
parentEpml.ready().then(() => {
|
||||
@ -217,6 +226,16 @@ class ChatHead extends LitElement {
|
||||
parentEpml.imReady()
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark'
|
||||
} else {
|
||||
this.theme = 'light'
|
||||
}
|
||||
document.querySelector('html').setAttribute('theme', this.theme)
|
||||
}
|
||||
|
||||
shouldUpdate(changedProperties) {
|
||||
if(changedProperties.has('activeChatHeadUrl')){
|
||||
return true
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { get, translate } from 'lit-translate';
|
||||
import { Epml } from '../../../epml';
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml'
|
||||
import snackbar from './snackbar.js'
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-dialog';
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@material/mwc-icon';
|
||||
import './WrapperModal';
|
||||
import '@material/mwc-icon'
|
||||
import './WrapperModal'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class ChatLeaveGroup extends LitElement {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { get, translate } from 'lit-translate';
|
||||
import { Epml } from '../../../epml';
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml'
|
||||
import snackbar from './snackbar.js'
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-dialog';
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
@ -18,15 +18,15 @@ class ChatModals extends LitElement {
|
||||
hidePrivateMessageModal: {type: Function},
|
||||
hideBlockUserModal: {type: Function},
|
||||
toblockaddress: { type: String, attribute: true },
|
||||
chatBlockedAdresses: { type: Array },
|
||||
chatBlockedAdresses: { type: Array }
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.isLoading = false;
|
||||
this.hidePrivateMessageModal = () => {};
|
||||
this.hideBlockUserModal = () => {};
|
||||
super()
|
||||
this.isLoading = false
|
||||
this.hidePrivateMessageModal = () => {}
|
||||
this.hideBlockUserModal = () => {}
|
||||
this.chatBlockedAdresses = []
|
||||
}
|
||||
|
||||
@ -105,13 +105,13 @@ class ChatModals extends LitElement {
|
||||
} else {
|
||||
this.sendMessage()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async sendMessage() {
|
||||
this.isLoading = true;
|
||||
const _recipient = this.shadowRoot.getElementById('sendTo').value;
|
||||
const messageBox = this.shadowRoot.getElementById('messageBox');
|
||||
const messageText = messageBox.value;
|
||||
this.isLoading = true
|
||||
const _recipient = this.shadowRoot.getElementById('sendTo').value
|
||||
const messageBox = this.shadowRoot.getElementById('messageBox')
|
||||
const messageText = messageBox.value
|
||||
let recipient;
|
||||
|
||||
const validateName = async (receiverName) => {
|
||||
@ -127,7 +127,7 @@ class ChatModals extends LitElement {
|
||||
myRes = myNameRes
|
||||
}
|
||||
|
||||
return myRes;
|
||||
return myRes
|
||||
}
|
||||
|
||||
const myNameRes = await validateName(_recipient)
|
||||
@ -138,8 +138,8 @@ class ChatModals extends LitElement {
|
||||
|
||||
recipient = myNameRes.owner
|
||||
}
|
||||
let _reference = new Uint8Array(64);
|
||||
window.crypto.getRandomValues(_reference);
|
||||
let _reference = new Uint8Array(64)
|
||||
window.crypto.getRandomValues(_reference)
|
||||
|
||||
let sendTimestamp = Date.now()
|
||||
|
||||
@ -200,17 +200,17 @@ class ChatModals extends LitElement {
|
||||
|
||||
const _computePow = async (chatBytes) => {
|
||||
|
||||
const _chatBytesArray = Object.keys(chatBytes).map(function (key) { return chatBytes[key]; });
|
||||
const _chatBytesArray = Object.keys(chatBytes).map(function (key) { return chatBytes[key]; })
|
||||
const chatBytesArray = new Uint8Array(_chatBytesArray)
|
||||
const chatBytesHash = new window.parent.Sha256().process(chatBytesArray).finish().result
|
||||
const hashPtr = window.parent.sbrk(32, window.parent.heap);
|
||||
const hashAry = new Uint8Array(window.parent.memory.buffer, hashPtr, 32);
|
||||
hashAry.set(chatBytesHash);
|
||||
const hashPtr = window.parent.sbrk(32, window.parent.heap)
|
||||
const hashAry = new Uint8Array(window.parent.memory.buffer, hashPtr, 32)
|
||||
hashAry.set(chatBytesHash)
|
||||
|
||||
const difficulty = this.balance < 4 ? 18 : 8;
|
||||
const difficulty = this.balance < 4 ? 18 : 8
|
||||
|
||||
const workBufferLength = 8 * 1024 * 1024;
|
||||
const workBufferPtr = window.parent.sbrk(workBufferLength, window.parent.heap);
|
||||
const workBufferPtr = window.parent.sbrk(workBufferLength, window.parent.heap)
|
||||
|
||||
let nonce = window.parent.computePow(hashPtr, workBufferPtr, workBufferLength, difficulty)
|
||||
|
||||
@ -250,9 +250,9 @@ class ChatModals extends LitElement {
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
let apiKey = myNode.apiKey
|
||||
return apiKey
|
||||
}
|
||||
|
||||
getChatBlockedList() {
|
||||
@ -263,7 +263,7 @@ class ChatModals extends LitElement {
|
||||
|
||||
localStorage.removeItem("ChatBlockedAddresses")
|
||||
|
||||
var obj = [];
|
||||
var obj = []
|
||||
|
||||
fetch(blockedAddressesUrl).then(response => {
|
||||
return response.json()
|
||||
@ -412,4 +412,4 @@ class ChatModals extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('chat-modals', ChatModals);
|
||||
customElements.define('chat-modals', ChatModals)
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,5 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { render } from "lit/html.js";
|
||||
import { get, translate } from "lit-translate";
|
||||
import { Epml } from "../../../epml";
|
||||
import { getUserNameFromAddress } from "../../utils/getUserNameFromAddress";
|
||||
import snackbar from "./snackbar.js";
|
||||
@ -13,6 +12,9 @@ import '@vaadin/button';
|
||||
import "./WrapperModal";
|
||||
import "./TipUser"
|
||||
import "./UserInfo/UserInfo";
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class ChatRightPanel extends LitElement {
|
||||
static get properties() {
|
||||
|
@ -1,57 +1,63 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
import { translate, get } from 'lit-translate';
|
||||
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { repeat } from 'lit/directives/repeat.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
import { unsafeHTML } from 'lit/directives/unsafe-html.js'
|
||||
import { chatStyles } from './ChatScroller-css.js'
|
||||
import { Epml } from "../../../epml";
|
||||
import { cropAddress } from "../../utils/cropAddress";
|
||||
import { roundToNearestDecimal } from '../../utils/roundToNearestDecimal.js';
|
||||
import './LevelFounder.js';
|
||||
import './NameMenu.js';
|
||||
import './ChatModals.js';
|
||||
import './WrapperModal';
|
||||
import "./UserInfo/UserInfo";
|
||||
import '@vaadin/icons';
|
||||
import '@vaadin/icon';
|
||||
import '@vaadin/tooltip';
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-dialog';
|
||||
import '@material/mwc-icon';
|
||||
import { EmojiPicker } from 'emoji-picker-js';
|
||||
import { generateHTML } from '@tiptap/core';
|
||||
import axios from "axios";
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import Underline from '@tiptap/extension-underline';
|
||||
import { Epml } from '../../../epml'
|
||||
import { cropAddress } from "../../utils/cropAddress"
|
||||
import { roundToNearestDecimal } from '../../utils/roundToNearestDecimal.js'
|
||||
import { EmojiPicker } from 'emoji-picker-js'
|
||||
import { generateHTML } from '@tiptap/core'
|
||||
import isElectron from 'is-electron'
|
||||
|
||||
import axios from 'axios'
|
||||
import Highlight from '@tiptap/extension-highlight'
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
import ShortUniqueId from 'short-unique-id'
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import Underline from '@tiptap/extension-underline'
|
||||
|
||||
import './ChatModals.js'
|
||||
import './LevelFounder.js'
|
||||
import './NameMenu.js'
|
||||
import './UserInfo/UserInfo.js'
|
||||
import './WrapperModal'
|
||||
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
import '@material/mwc-icon'
|
||||
import '@vaadin/icon'
|
||||
import '@vaadin/icons'
|
||||
import '@vaadin/tooltip'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
let toggledMessage = {}
|
||||
|
||||
const uid = new ShortUniqueId()
|
||||
|
||||
const getApiKey = () => {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
let apiKey = myNode.apiKey
|
||||
return apiKey
|
||||
}
|
||||
|
||||
const extractComponents = async (url) => {
|
||||
if (!url.startsWith("qortal://")) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
url = url.replace(/^(qortal\:\/\/)/, "");
|
||||
url = url.replace(/^(qortal\:\/\/)/, "")
|
||||
if (url.includes("/")) {
|
||||
let parts = url.split("/");
|
||||
const service = parts[0].toUpperCase();
|
||||
parts.shift();
|
||||
const name = parts[0];
|
||||
parts.shift();
|
||||
let identifier;
|
||||
let parts = url.split("/")
|
||||
const service = parts[0].toUpperCase()
|
||||
parts.shift()
|
||||
const name = parts[0]
|
||||
parts.shift()
|
||||
let identifier
|
||||
|
||||
if (parts.length > 0) {
|
||||
identifier = parts[0]; // Do not shift yet
|
||||
identifier = parts[0] // Do not shift yet
|
||||
// Check if a resource exists with this service, name and identifier combination
|
||||
let responseObj = await parentEpml.request('apiCall', {
|
||||
url: `/arbitrary/resource/status/${service}/${name}/${identifier}?apiKey=${getApiKey()}`
|
||||
@ -59,48 +65,48 @@ const extractComponents = async (url) => {
|
||||
|
||||
if (responseObj.totalChunkCount > 0) {
|
||||
// Identifier exists, so don't include it in the path
|
||||
parts.shift();
|
||||
parts.shift()
|
||||
}
|
||||
else {
|
||||
identifier = null;
|
||||
identifier = null
|
||||
}
|
||||
}
|
||||
|
||||
const path = parts.join("/");
|
||||
const path = parts.join("/")
|
||||
|
||||
const components = {};
|
||||
components["service"] = service;
|
||||
components["name"] = name;
|
||||
components["identifier"] = identifier;
|
||||
components["path"] = path;
|
||||
return components;
|
||||
const components = {}
|
||||
components["service"] = service
|
||||
components["name"] = name
|
||||
components["identifier"] = identifier
|
||||
components["path"] = path
|
||||
return components
|
||||
}
|
||||
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
function processText(input) {
|
||||
const linkRegex = /(qortal:\/\/\S+)/g;
|
||||
const linkRegex = /(qortal:\/\/\S+)/g
|
||||
|
||||
function processNode(node) {
|
||||
if (node.nodeType === Node.TEXT_NODE) {
|
||||
const parts = node.textContent.split(linkRegex);
|
||||
const parts = node.textContent.split(linkRegex)
|
||||
|
||||
if (parts.length > 1) {
|
||||
const fragment = document.createDocumentFragment();
|
||||
const fragment = document.createDocumentFragment()
|
||||
|
||||
parts.forEach((part) => {
|
||||
if (part.startsWith('qortal://')) {
|
||||
const link = document.createElement('span');
|
||||
const link = document.createElement('span')
|
||||
// Store the URL in a data attribute
|
||||
link.setAttribute('data-url', part);
|
||||
link.textContent = part;
|
||||
link.style.color = 'var(--nav-text-color)';
|
||||
link.style.textDecoration = 'underline';
|
||||
link.setAttribute('data-url', part)
|
||||
link.textContent = part
|
||||
link.style.color = 'var(--nav-text-color)'
|
||||
link.style.textDecoration = 'underline'
|
||||
link.style.cursor = 'pointer'
|
||||
|
||||
link.addEventListener('click', async (e) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
try {
|
||||
const res = await extractComponents(part)
|
||||
if (!res) return
|
||||
@ -134,34 +140,36 @@ function processText(input) {
|
||||
console.log({ error })
|
||||
}
|
||||
|
||||
});
|
||||
})
|
||||
|
||||
fragment.appendChild(link);
|
||||
fragment.appendChild(link)
|
||||
} else {
|
||||
const textNode = document.createTextNode(part);
|
||||
fragment.appendChild(textNode);
|
||||
const textNode = document.createTextNode(part)
|
||||
fragment.appendChild(textNode)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
node.replaceWith(fragment);
|
||||
node.replaceWith(fragment)
|
||||
}
|
||||
} else {
|
||||
for (const childNode of Array.from(node.childNodes)) {
|
||||
processNode(childNode);
|
||||
processNode(childNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.innerHTML = input;
|
||||
const wrapper = document.createElement('div')
|
||||
wrapper.innerHTML = input
|
||||
|
||||
processNode(wrapper);
|
||||
processNode(wrapper)
|
||||
|
||||
return wrapper
|
||||
}
|
||||
|
||||
class ChatScroller extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
theme: { type: String, reflect: true },
|
||||
getNewMessage: { attribute: false },
|
||||
getOldMessage: { attribute: false },
|
||||
escapeHTML: { attribute: false },
|
||||
@ -193,7 +201,7 @@ class ChatScroller extends LitElement {
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [chatStyles];
|
||||
return [chatStyles]
|
||||
}
|
||||
|
||||
constructor() {
|
||||
@ -203,9 +211,10 @@ class ChatScroller extends LitElement {
|
||||
this._downObserverHandler = this._downObserverHandler.bind(this)
|
||||
this.myAddress = window.parent.reduxStore.getState().app.selectedAddress.address
|
||||
this.hideMessages = JSON.parse(localStorage.getItem("MessageBlockedAddresses") || "[]")
|
||||
this.openTipUser = false;
|
||||
this.openUserInfo = false;
|
||||
this.openTipUser = false
|
||||
this.openUserInfo = false
|
||||
this.listSeenMessages = []
|
||||
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
|
||||
}
|
||||
|
||||
addSeenMessage(val) {
|
||||
@ -214,42 +223,41 @@ class ChatScroller extends LitElement {
|
||||
|
||||
render() {
|
||||
let formattedMessages = this.messages.reduce((messageArray, message, index) => {
|
||||
const lastGroupedMessage = messageArray[messageArray.length - 1];
|
||||
let timestamp;
|
||||
let sender;
|
||||
let repliedToData;
|
||||
let firstMessageInChat;
|
||||
const lastGroupedMessage = messageArray[messageArray.length - 1]
|
||||
let timestamp
|
||||
let sender
|
||||
let repliedToData
|
||||
let firstMessageInChat
|
||||
|
||||
if (index === 0) {
|
||||
firstMessageInChat = true;
|
||||
firstMessageInChat = true
|
||||
} else {
|
||||
firstMessageInChat = false;
|
||||
firstMessageInChat = false
|
||||
}
|
||||
|
||||
message = { ...message, firstMessageInChat }
|
||||
|
||||
if (lastGroupedMessage) {
|
||||
timestamp = lastGroupedMessage.timestamp;
|
||||
sender = lastGroupedMessage.sender;
|
||||
repliedToData = lastGroupedMessage.repliedToData;
|
||||
timestamp = lastGroupedMessage.timestamp
|
||||
sender = lastGroupedMessage.sender
|
||||
repliedToData = lastGroupedMessage.repliedToData
|
||||
}
|
||||
const isSameGroup = Math.abs(timestamp - message.timestamp) < 600000 && sender === message.sender && !repliedToData;
|
||||
const isSameGroup = Math.abs(timestamp - message.timestamp) < 600000 && sender === message.sender && !repliedToData
|
||||
|
||||
if (isSameGroup) {
|
||||
messageArray[messageArray.length - 1].messages = [
|
||||
...(messageArray[messageArray.length - 1].messages || []),
|
||||
message
|
||||
];
|
||||
]
|
||||
} else {
|
||||
messageArray.push({
|
||||
messages: [message],
|
||||
...message
|
||||
});
|
||||
})
|
||||
}
|
||||
return messageArray;
|
||||
return messageArray
|
||||
}, [])
|
||||
|
||||
|
||||
return html`
|
||||
${this.isLoadingMessages ? html`
|
||||
<div class="spinnerContainer">
|
||||
@ -312,37 +320,72 @@ class ChatScroller extends LitElement {
|
||||
return true
|
||||
}
|
||||
// Only update element if prop1 changed.
|
||||
return changedProperties.has('messages');
|
||||
return changedProperties.has('messages')
|
||||
}
|
||||
|
||||
async getUpdateComplete() {
|
||||
await super.getUpdateComplete();
|
||||
const marginElements = Array.from(this.shadowRoot.querySelectorAll('message-template'));
|
||||
await Promise.all(marginElements.map(el => el.updateComplete));
|
||||
return true;
|
||||
await super.getUpdateComplete()
|
||||
const marginElements = Array.from(this.shadowRoot.querySelectorAll('message-template'))
|
||||
await Promise.all(marginElements.map(el => el.updateComplete))
|
||||
return true
|
||||
}
|
||||
|
||||
setToggledMessage(message) {
|
||||
toggledMessage = message;
|
||||
toggledMessage = message
|
||||
}
|
||||
|
||||
async firstUpdated() {
|
||||
this.emojiPicker.on('emoji', selection => {
|
||||
this.changeTheme()
|
||||
|
||||
window.addEventListener('storage', () => {
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark'
|
||||
} else {
|
||||
this.theme = 'light'
|
||||
}
|
||||
document.querySelector('html').setAttribute('theme', this.theme)
|
||||
})
|
||||
|
||||
this.emojiPicker.on('emoji', selection => {
|
||||
this.sendMessage({
|
||||
type: 'reaction',
|
||||
editedMessageObj: toggledMessage,
|
||||
reaction: selection.emoji,
|
||||
})
|
||||
});
|
||||
this.viewElement = this.shadowRoot.getElementById('viewElement');
|
||||
this.upObserverElement = this.shadowRoot.getElementById('upObserver');
|
||||
this.downObserverElement = this.shadowRoot.getElementById('downObserver');
|
||||
})
|
||||
this.viewElement = this.shadowRoot.getElementById('viewElement')
|
||||
this.upObserverElement = this.shadowRoot.getElementById('upObserver')
|
||||
this.downObserverElement = this.shadowRoot.getElementById('downObserver')
|
||||
// Intialize Observers
|
||||
this.upElementObserver();
|
||||
this.downElementObserver();
|
||||
await this.getUpdateComplete();
|
||||
this.viewElement.scrollTop = this.viewElement.scrollHeight + 50;
|
||||
this.upElementObserver()
|
||||
this.downElementObserver()
|
||||
await this.getUpdateComplete()
|
||||
this.viewElement.scrollTop = this.viewElement.scrollHeight + 50
|
||||
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark'
|
||||
} else {
|
||||
this.theme = 'light'
|
||||
}
|
||||
document.querySelector('html').setAttribute('theme', this.theme)
|
||||
}
|
||||
|
||||
_getOldMessage(_scrollElement) {
|
||||
@ -358,19 +401,19 @@ class ChatScroller extends LitElement {
|
||||
if (this.messages.length < 20) {
|
||||
return
|
||||
}
|
||||
this.setIsLoadingMessages(true);
|
||||
let _scrollElement = entries[0].target.nextElementSibling;
|
||||
this._getOldMessage(_scrollElement);
|
||||
this.setIsLoadingMessages(true)
|
||||
let _scrollElement = entries[0].target.nextElementSibling
|
||||
this._getOldMessage(_scrollElement)
|
||||
}
|
||||
}
|
||||
|
||||
_downObserverHandler(entries) {
|
||||
if (!entries[0].isIntersecting) {
|
||||
let _scrollElement = entries[0].target.previousElementSibling;
|
||||
// this._getOldMessageAfter(_scrollElement);
|
||||
this.showLastMessageRefScroller(true);
|
||||
let _scrollElement = entries[0].target.previousElementSibling
|
||||
// this._getOldMessageAfter(_scrollElement)
|
||||
this.showLastMessageRefScroller(true)
|
||||
} else {
|
||||
this.showLastMessageRefScroller(false);
|
||||
this.showLastMessageRefScroller(false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,9 +422,9 @@ class ChatScroller extends LitElement {
|
||||
root: this.viewElement,
|
||||
rootMargin: '0px',
|
||||
threshold: 1
|
||||
};
|
||||
const observer = new IntersectionObserver(this._upObserverhandler, options);
|
||||
observer.observe(this.upObserverElement);
|
||||
}
|
||||
const observer = new IntersectionObserver(this._upObserverhandler, options)
|
||||
observer.observe(this.upObserverElement)
|
||||
}
|
||||
|
||||
downElementObserver() {
|
||||
@ -391,12 +434,12 @@ class ChatScroller extends LitElement {
|
||||
threshold: 1
|
||||
}
|
||||
// identify an element to observe
|
||||
const elementToObserve = this.downObserverElement;
|
||||
const elementToObserve = this.downObserverElement
|
||||
// passing it a callback function
|
||||
const observer = new IntersectionObserver(this._downObserverHandler, options);
|
||||
const observer = new IntersectionObserver(this._downObserverHandler, options)
|
||||
// call `observe()` on that MutationObserver instance,
|
||||
// passing it the element to observe, and the options object
|
||||
observer.observe(elementToObserve);
|
||||
observer.observe(elementToObserve)
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,12 +480,12 @@ class MessageTemplate extends LitElement {
|
||||
goToRepliedMessage: { attribute: false },
|
||||
listSeenMessages: { type: Array },
|
||||
addSeenMessage: { attribute: false },
|
||||
chatId: { type: String },
|
||||
chatId: { type: String }
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
super()
|
||||
this.messageObj = {}
|
||||
this.openDialogPrivateMessage = false
|
||||
this.openDialogBlockUser = false
|
||||
@ -461,7 +504,7 @@ class MessageTemplate extends LitElement {
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [chatStyles];
|
||||
return [chatStyles]
|
||||
}
|
||||
|
||||
|
||||
@ -485,26 +528,26 @@ class MessageTemplate extends LitElement {
|
||||
|
||||
showBlockIconFunc(bool) {
|
||||
if (bool) {
|
||||
this.showBlockAddressIcon = true;
|
||||
this.showBlockAddressIcon = true
|
||||
} else {
|
||||
this.showBlockAddressIcon = false;
|
||||
this.showBlockAddressIcon = false
|
||||
}
|
||||
}
|
||||
|
||||
async downloadAttachment(attachment) {
|
||||
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
try {
|
||||
axios.get(`${nodeUrl}/arbitrary/QCHAT_ATTACHMENT/${attachment.name}/${attachment.identifier}?apiKey=${myNode.apiKey}`, { responseType: 'blob' })
|
||||
.then(response => {
|
||||
let filename = attachment.attachmentName;
|
||||
let blob = new Blob([response.data], { type: "application/octet-stream" });
|
||||
this.saveFileToDisk(blob, filename);
|
||||
let filename = attachment.attachmentName
|
||||
let blob = new Blob([response.data], { type: "application/octet-stream" })
|
||||
this.saveFileToDisk(blob, filename)
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
@ -533,31 +576,43 @@ class MessageTemplate extends LitElement {
|
||||
this.viewImage = true
|
||||
}
|
||||
|
||||
const tooltips = this.shadowRoot.querySelectorAll('vaadin-tooltip');
|
||||
const tooltips = this.shadowRoot.querySelectorAll('vaadin-tooltip')
|
||||
tooltips.forEach(tooltip => {
|
||||
const overlay = tooltip.shadowRoot.querySelector('vaadin-tooltip-overlay');
|
||||
overlay.shadowRoot.getElementById("overlay").style.cssText = "background-color: transparent; box-shadow: rgb(50 50 93 / 25%) 0px 2px 5px -1px, rgb(0 0 0 / 30%) 0px 1px 3px -1px";
|
||||
overlay.shadowRoot.getElementById('content').style.cssText = "background-color: var(--reactions-tooltip-bg); color: var(--chat-bubble-msg-color); text-align: center; padding: 20px 10px; border-radius: 8px; font-family: Roboto, sans-serif; letter-spacing: 0.3px; font-weight: 300; font-size: 13.5px; transition: all 0.3s ease-in-out;";
|
||||
});
|
||||
const overlay = tooltip.shadowRoot.querySelector('vaadin-tooltip-overlay')
|
||||
overlay.shadowRoot.getElementById("overlay").style.cssText = "background-color: transparent; box-shadow: rgb(50 50 93 / 25%) 0px 2px 5px -1px, rgb(0 0 0 / 30%) 0px 1px 3px -1px"
|
||||
overlay.shadowRoot.getElementById('content').style.cssText = "background-color: var(--reactions-tooltip-bg); color: var(--chat-bubble-msg-color); text-align: center; padding: 20px 10px; border-radius: 8px; font-family: Roboto, sans-serif; letter-spacing: 0.3px; font-weight: 300; font-size: 13.5px; transition: all 0.3s ease-in-out;"
|
||||
})
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const hidemsg = this.hideMessages;
|
||||
let message = "";
|
||||
const hidemsg = this.hideMessages
|
||||
let message = ""
|
||||
let messageVersion2 = ""
|
||||
let messageVersion2WithLink = null
|
||||
let reactions = [];
|
||||
let repliedToData = null;
|
||||
let image = null;
|
||||
let gif = null;
|
||||
let isImageDeleted = false;
|
||||
let isAttachmentDeleted = false;
|
||||
let version = 0;
|
||||
let reactions = []
|
||||
let repliedToData = null
|
||||
let image = null
|
||||
let gif = null
|
||||
let isImageDeleted = false
|
||||
let isAttachmentDeleted = false
|
||||
let version = 0
|
||||
let isForwarded = false
|
||||
let isEdited = false
|
||||
let attachment = null;
|
||||
let attachment = null
|
||||
try {
|
||||
const parsedMessageObj = JSON.parse(this.messageObj.decodedMessage);
|
||||
const parsedMessageObj = JSON.parse(this.messageObj.decodedMessage)
|
||||
if (+parsedMessageObj.version > 1 && parsedMessageObj.messageText) {
|
||||
messageVersion2 = generateHTML(parsedMessageObj.messageText, [
|
||||
StarterKit,
|
||||
@ -568,121 +623,122 @@ class MessageTemplate extends LitElement {
|
||||
messageVersion2WithLink = processText(messageVersion2)
|
||||
|
||||
}
|
||||
message = parsedMessageObj.messageText;
|
||||
repliedToData = this.messageObj.repliedToData;
|
||||
isImageDeleted = parsedMessageObj.isImageDeleted;
|
||||
isAttachmentDeleted = parsedMessageObj.isAttachmentDeleted;
|
||||
// reactions = parsedMessageObj.reactions || [];
|
||||
version = parsedMessageObj.version;
|
||||
isForwarded = parsedMessageObj.type === 'forward';
|
||||
isEdited = parsedMessageObj.isEdited && true;
|
||||
message = parsedMessageObj.messageText
|
||||
repliedToData = this.messageObj.repliedToData
|
||||
isImageDeleted = parsedMessageObj.isImageDeleted
|
||||
isAttachmentDeleted = parsedMessageObj.isAttachmentDeleted
|
||||
// reactions = parsedMessageObj.reactions || []
|
||||
version = parsedMessageObj.version
|
||||
isForwarded = parsedMessageObj.type === 'forward'
|
||||
isEdited = parsedMessageObj.isEdited && true
|
||||
if (parsedMessageObj.attachments && Array.isArray(parsedMessageObj.attachments) && parsedMessageObj.attachments.length > 0) {
|
||||
attachment = parsedMessageObj.attachments[0];
|
||||
attachment = parsedMessageObj.attachments[0]
|
||||
}
|
||||
if (parsedMessageObj.images && Array.isArray(parsedMessageObj.images) && parsedMessageObj.images.length > 0) {
|
||||
image = parsedMessageObj.images[0];
|
||||
image = parsedMessageObj.images[0]
|
||||
}
|
||||
if (parsedMessageObj.gifs && Array.isArray(parsedMessageObj.gifs) && parsedMessageObj.gifs.length > 0) {
|
||||
gif = parsedMessageObj.gifs[0];
|
||||
gif = parsedMessageObj.gifs[0]
|
||||
}
|
||||
} catch (error) {
|
||||
message = this.messageObj.decodedMessage;
|
||||
message = this.messageObj.decodedMessage
|
||||
}
|
||||
let avatarImg = '';
|
||||
let imageHTML = '';
|
||||
let imageHTMLDialog = '';
|
||||
let imageUrl = '';
|
||||
let gifHTML = '';
|
||||
let gifHTMLDialog = '';
|
||||
let gifUrl = '';
|
||||
let nameMenu = '';
|
||||
let levelFounder = '';
|
||||
let hideit = hidemsg.includes(this.messageObj.sender);
|
||||
let avatarImg = ''
|
||||
let imageHTML = ''
|
||||
let imageHTMLDialog = ''
|
||||
let imageUrl = ''
|
||||
let gifHTML = ''
|
||||
let gifHTMLDialog = ''
|
||||
let gifUrl = ''
|
||||
let nameMenu = ''
|
||||
let levelFounder = ''
|
||||
let hideit = hidemsg.includes(this.messageObj.sender)
|
||||
let forwarded = ''
|
||||
let edited = ''
|
||||
|
||||
levelFounder = html`<level-founder checkleveladdress="${this.messageObj.sender}"></level-founder>`;
|
||||
levelFounder = html`<level-founder checkleveladdress="${this.messageObj.sender}"></level-founder>`
|
||||
|
||||
if (this.messageObj.senderName) {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
const avatarUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${this.messageObj.senderName}/qortal_avatar?async=true&apiKey=${myNode.apiKey}`;
|
||||
avatarImg = html`<img src="${avatarUrl}" style="max-width:100%; max-height:100%;" onerror="this.onerror=null; this.src='/img/incognito.png';" />`;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
const avatarUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${this.messageObj.senderName}/qortal_avatar?async=true&apiKey=${myNode.apiKey}`
|
||||
avatarImg = html`<img src="${avatarUrl}" style="max-width:100%; max-height:100%;" onerror="this.onerror=null; this.src='/img/incognito.png';" />`
|
||||
} else {
|
||||
avatarImg = html`<img src='/img/incognito.png' style="max-width:100%; max-height:100%;" onerror="this.onerror=null;" />`
|
||||
}
|
||||
|
||||
const createImage = (imageUrl) => {
|
||||
const imageHTMLRes = new Image();
|
||||
imageHTMLRes.src = imageUrl;
|
||||
imageHTMLRes.style = "max-width:45vh; max-height:40vh; border-radius: 5px; cursor: pointer";
|
||||
const imageHTMLRes = new Image()
|
||||
imageHTMLRes.src = imageUrl
|
||||
imageHTMLRes.style = "max-width:45vh; max-height:40vh; border-radius: 5px; cursor: pointer;"
|
||||
imageHTMLRes.onclick = () => {
|
||||
this.openDialogImage = true;
|
||||
this.openDialogImage = true
|
||||
}
|
||||
imageHTMLRes.onload = () => {
|
||||
this.isImageLoaded = true;
|
||||
this.isImageLoaded = true
|
||||
}
|
||||
imageHTMLRes.onerror = () => {
|
||||
if (this.imageFetches < 4) {
|
||||
setTimeout(() => {
|
||||
this.imageFetches = this.imageFetches + 1;
|
||||
imageHTMLRes.src = imageUrl;
|
||||
}, 2000);
|
||||
this.imageFetches = this.imageFetches + 1
|
||||
imageHTMLRes.src = imageUrl
|
||||
}, 10000)
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
this.imageFetches = this.imageFetches + 1;
|
||||
imageHTMLRes.src = imageUrl;
|
||||
}, 6000);
|
||||
this.imageFetches = this.imageFetches + 1
|
||||
imageHTMLRes.src = imageUrl
|
||||
}, 15000)
|
||||
}
|
||||
};
|
||||
return imageHTMLRes;
|
||||
}
|
||||
return imageHTMLRes
|
||||
}
|
||||
|
||||
const createGif = (gif) => {
|
||||
const gifHTMLRes = new Image();
|
||||
gifHTMLRes.src = gif;
|
||||
gifHTMLRes.style = "max-width:45vh; max-height:40vh; border-radius: 5px; cursor: pointer";
|
||||
const gifHTMLRes = new Image()
|
||||
gifHTMLRes.src = gif
|
||||
gifHTMLRes.style = "max-width:45vh; max-height:40vh; border-radius: 5px; cursor: pointer;"
|
||||
gifHTMLRes.onclick = () => {
|
||||
this.openDialogGif = true;
|
||||
this.openDialogGif = true
|
||||
}
|
||||
gifHTMLRes.onload = () => {
|
||||
this.isGifLoaded = true;
|
||||
this.isGifLoaded = true
|
||||
}
|
||||
gifHTMLRes.onerror = () => {
|
||||
if (this.gifFetches < 4) {
|
||||
setTimeout(() => {
|
||||
this.gifFetches = this.gifFetches + 1;
|
||||
gifHTMLRes.src = gif;
|
||||
}, 500);
|
||||
this.gifFetches = this.gifFetches + 1
|
||||
gifHTMLRes.src = gif
|
||||
}, 10000)
|
||||
} else {
|
||||
gifHTMLRes.src = '/img/chain.png';
|
||||
gifHTMLRes.style = "max-width:45vh; max-height:20vh; border-radius: 5px; filter: opacity(0.5)";
|
||||
gifHTMLRes.src = '/img/chain.png'
|
||||
gifHTMLRes.style = "max-width:45vh; max-height:20vh; border-radius: 5px; filter: opacity(0.5);"
|
||||
gifHTMLRes.onclick = () => { }
|
||||
this.isGifLoaded = true
|
||||
}
|
||||
};
|
||||
return gifHTMLRes;
|
||||
}
|
||||
return gifHTMLRes
|
||||
}
|
||||
|
||||
if (image) {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
imageUrl = `${nodeUrl}/arbitrary/${image.service}/${image.name}/${image.identifier}?async=true&apiKey=${myNode.apiKey}`;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
imageUrl = `${nodeUrl}/arbitrary/${image.service}/${image.name}/${image.identifier}?async=true&apiKey=${myNode.apiKey}`
|
||||
|
||||
if (this.viewImage || this.myAddress === this.messageObj.sender) {
|
||||
imageHTML = createImage(imageUrl);
|
||||
imageHTML = createImage(imageUrl)
|
||||
imageHTMLDialog = createImage(imageUrl)
|
||||
imageHTMLDialog.style = "height: auto; max-height: 80vh; width: auto; max-width: 80vw; object-fit: contain; border-radius: 5px";
|
||||
imageHTMLDialog.style = "height: auto; max-height: 80vh; width: auto; max-width: 80vw; object-fit: contain; border-radius: 5px;"
|
||||
}
|
||||
}
|
||||
|
||||
if (gif) {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
gifUrl = `${nodeUrl}/arbitrary/${gif.service}/${gif.name}/${gif.identifier}?filepath=${gif.filePath}&apiKey=${myNode.apiKey}`;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
gifUrl = `${nodeUrl}/arbitrary/${gif.service}/${gif.name}/${gif.identifier}?filepath=${gif.filePath}&apiKey=${myNode.apiKey}`
|
||||
if (this.viewImage || this.myAddress === this.messageObj.sender) {
|
||||
gifHTML = createGif(gifUrl);
|
||||
gifHTML = createGif(gifUrl)
|
||||
gifHTMLDialog = createGif(gifUrl)
|
||||
gifHTMLDialog.style = "height: auto; max-height: 80vh; width: auto; max-width: 80vw; object-fit: contain; border-radius: 5px";
|
||||
gifHTMLDialog.style = "height: auto; max-height: 80vh; width: auto; max-width: 80vw; object-fit: contain; border-radius: 5px;"
|
||||
}
|
||||
}
|
||||
|
||||
@ -690,27 +746,29 @@ class MessageTemplate extends LitElement {
|
||||
<span class="${this.messageObj.sender === this.myAddress && 'message-data-my-name'}">
|
||||
${this.messageObj.senderName ? this.messageObj.senderName : cropAddress(this.messageObj.sender)}
|
||||
</span>
|
||||
`;
|
||||
`
|
||||
|
||||
forwarded = html`
|
||||
<span class="${this.messageObj.sender === this.myAddress && 'message-data-forward'}">
|
||||
${translate("blockpage.bcchange17")}
|
||||
</span>
|
||||
`;
|
||||
<span class="${this.messageObj.sender === this.myAddress && 'message-data-forward'}">
|
||||
${translate("blockpage.bcchange17")}
|
||||
</span>
|
||||
`
|
||||
|
||||
edited = html`
|
||||
<span class="edited-message-style">
|
||||
${translate("chatpage.cchange68")}
|
||||
</span>
|
||||
`;
|
||||
<span class="edited-message-style">
|
||||
${translate("chatpage.cchange68")}
|
||||
</span>
|
||||
`
|
||||
|
||||
if (repliedToData) {
|
||||
try {
|
||||
const parsedMsg = JSON.parse(repliedToData.decodedMessage);
|
||||
repliedToData.decodedMessage = parsedMsg;
|
||||
const parsedMsg = JSON.parse(repliedToData.decodedMessage)
|
||||
repliedToData.decodedMessage = parsedMsg
|
||||
} catch (error) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let repliedToMessageText = ''
|
||||
if (repliedToData && repliedToData.decodedMessage && repliedToData.decodedMessage.messageText) {
|
||||
try {
|
||||
@ -724,16 +782,16 @@ class MessageTemplate extends LitElement {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
let replacedMessage = ''
|
||||
if (message && +version < 2) {
|
||||
const escapedMessage = this.escapeHTML(message)
|
||||
if (escapedMessage) {
|
||||
replacedMessage = escapedMessage.replace(new RegExp('\r?\n', 'g'), '<br />');
|
||||
replacedMessage = escapedMessage.replace(new RegExp('\r?\n', 'g'), '<br />')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return hideit ? html`<li class="clearfix"></li>` : html`
|
||||
<li
|
||||
class="clearfix message-parent"
|
||||
@ -753,9 +811,9 @@ class MessageTemplate extends LitElement {
|
||||
<div
|
||||
style=${this.myAddress === this.messageObj.sender ? "cursor: auto;" : "cursor: pointer;"}
|
||||
@click=${() => {
|
||||
if (this.myAddress === this.messageObj.sender) return;
|
||||
this.setOpenUserInfo(true);
|
||||
this.setUserName(this.messageObj);
|
||||
if (this.myAddress === this.messageObj.sender) return
|
||||
this.setOpenUserInfo(true)
|
||||
this.setUserName(this.messageObj)
|
||||
}} class="message-data-avatar">
|
||||
${avatarImg}
|
||||
</div>
|
||||
@ -789,9 +847,9 @@ class MessageTemplate extends LitElement {
|
||||
<span
|
||||
style=${this.myAddress === this.messageObj.sender ? "cursor: auto;" : "cursor: pointer;"}
|
||||
@click=${() => {
|
||||
if (this.myAddress === this.messageObj.sender) return;
|
||||
this.setOpenUserInfo(true);
|
||||
this.setUserName(this.messageObj);
|
||||
if (this.myAddress === this.messageObj.sender) return
|
||||
this.setOpenUserInfo(true)
|
||||
this.setUserName(this.messageObj)
|
||||
}}
|
||||
class="message-data-name">
|
||||
${nameMenu}
|
||||
@ -844,13 +902,13 @@ class MessageTemplate extends LitElement {
|
||||
}}
|
||||
class=${[`image-container`, !this.isImageLoaded ? 'defaultSize' : ''].join(' ')}
|
||||
style=${this.isFirstMessage && "margin-top: 10px;"}>
|
||||
<div style="display:flex;width:100%;height:100%;justify-content:center;align-items:center;cursor:pointer;color:var(--black)">
|
||||
<div style="display:flex;width:100%;height:100%;justify-content:center;align-items:center;cursor:pointer;color:var(--black);">
|
||||
${translate("chatpage.cchange40")}
|
||||
</div>
|
||||
</div>
|
||||
` : html``}
|
||||
${!this.isImageLoaded && image && this.viewImage ? html`
|
||||
<div style="display:flex;width:100%;height:100%;justify-content:center;align-items:center;position:absolute">
|
||||
<div style="display:flex;width:100%;height:100%;justify-content:center;align-items:center;position:absolute;">
|
||||
<div class=${`smallLoading`}></div>
|
||||
</div>
|
||||
|
||||
@ -863,7 +921,7 @@ class MessageTemplate extends LitElement {
|
||||
${this.myAddress === this.messageObj.sender ? html`
|
||||
<vaadin-icon
|
||||
@click=${() => {
|
||||
this.openDeleteImage = true;
|
||||
this.openDeleteImage = true
|
||||
}}
|
||||
class="image-delete-icon" icon="vaadin:close" slot="icon"></vaadin-icon>
|
||||
` : ''}
|
||||
@ -879,7 +937,7 @@ class MessageTemplate extends LitElement {
|
||||
}}
|
||||
class=${[`image-container`, !this.isImageLoaded ? 'defaultSize' : ''].join(' ')}
|
||||
style=${this.isFirstMessage && "margin-top: 10px;"}>
|
||||
<div style="display:flex;width:100%;height:100%;justify-content:center;align-items:center;cursor:pointer;color:var(--black)">
|
||||
<div style="display:flex;width:100%;height:100%;justify-content:center;align-items:center;cursor:pointer;color:var(--black);">
|
||||
${translate("gifs.gchange25")}
|
||||
</div>
|
||||
</div>
|
||||
@ -917,8 +975,8 @@ class MessageTemplate extends LitElement {
|
||||
? html`
|
||||
<vaadin-icon
|
||||
@click=${(e) => {
|
||||
e.stopPropagation();
|
||||
this.openDeleteAttachment = true;
|
||||
e.stopPropagation()
|
||||
this.openDeleteAttachment = true
|
||||
}}
|
||||
class="image-delete-icon" icon="vaadin:close" slot="icon">
|
||||
</vaadin-icon>
|
||||
@ -1128,7 +1186,7 @@ class MessageTemplate extends LitElement {
|
||||
hideActions
|
||||
?open=${this.openDeleteImage}
|
||||
@closed=${() => {
|
||||
this.openDeleteImage = false;
|
||||
this.openDeleteImage = false
|
||||
}}>
|
||||
<div class="delete-image-msg">
|
||||
<p>${translate("chatpage.cchange78")}</p>
|
||||
@ -1153,7 +1211,7 @@ class MessageTemplate extends LitElement {
|
||||
hideActions
|
||||
?open=${this.openDeleteAttachment}
|
||||
@closed=${() => {
|
||||
this.openDeleteAttachment = false;
|
||||
this.openDeleteAttachment = false
|
||||
}}>
|
||||
<div class="delete-image-msg">
|
||||
<p>${translate("chatpage.cchange79")}</p>
|
||||
@ -1182,7 +1240,7 @@ class MessageTemplate extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('message-template', MessageTemplate);
|
||||
window.customElements.define('message-template', MessageTemplate)
|
||||
|
||||
class ChatMenu extends LitElement {
|
||||
static get properties() {
|
||||
@ -1207,18 +1265,18 @@ class ChatMenu extends LitElement {
|
||||
setOpenPrivateMessage: { attribute: false },
|
||||
setOpenTipUser: { attribute: false },
|
||||
setUserName: { attribute: false },
|
||||
gif: { type: Boolean },
|
||||
gif: { type: Boolean }
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.showPrivateMessageModal = () => { };
|
||||
this.showBlockUserModal = () => { };
|
||||
super()
|
||||
this.showPrivateMessageModal = () => { }
|
||||
this.showBlockUserModal = () => { }
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [chatStyles];
|
||||
return [chatStyles]
|
||||
}
|
||||
|
||||
// Copy address to clipboard
|
||||
@ -1246,7 +1304,7 @@ class ChatMenu extends LitElement {
|
||||
key: ''
|
||||
}
|
||||
try {
|
||||
parsedMessageObj = JSON.parse(this.originalMessage.decodedMessage);
|
||||
parsedMessageObj = JSON.parse(this.originalMessage.decodedMessage)
|
||||
|
||||
} catch (error) {
|
||||
parsedMessageObj = {}
|
||||
@ -1335,7 +1393,7 @@ class ChatMenu extends LitElement {
|
||||
this.versionErrorSnack()
|
||||
return
|
||||
}
|
||||
this.setRepliedToMessageObj({ ...this.originalMessage, version: this.version });
|
||||
this.setRepliedToMessageObj({ ...this.originalMessage, version: this.version })
|
||||
}}">
|
||||
<vaadin-icon icon="vaadin:reply" slot="icon"></vaadin-icon>
|
||||
</div>
|
||||
@ -1351,7 +1409,7 @@ class ChatMenu extends LitElement {
|
||||
this.versionErrorSnack()
|
||||
return
|
||||
}
|
||||
this.setEditedMessageObj(this.originalMessage);
|
||||
this.setEditedMessageObj(this.originalMessage)
|
||||
}}>
|
||||
<vaadin-icon icon="vaadin:pencil" slot="icon"></vaadin-icon>
|
||||
</div>
|
||||
@ -1363,9 +1421,9 @@ class ChatMenu extends LitElement {
|
||||
class=${`menu-icon ${!this.firstMessageInChat ? "tooltip" : ""}`}
|
||||
data-text="${translate("blockpage.bcchange18")}"
|
||||
@click=${(e) => {
|
||||
e.preventDefault();
|
||||
this.setUserName(this.originalMessage);
|
||||
this.setOpenTipUser(true);
|
||||
e.preventDefault()
|
||||
this.setUserName(this.originalMessage)
|
||||
this.setOpenTipUser(true)
|
||||
}}>
|
||||
<vaadin-icon icon="vaadin:dollar" slot="icon"></vaadin-icon>
|
||||
</div>
|
||||
|
72
plugins/plugins/core/components/ChatSearchResults.js
Normal file
72
plugins/plugins/core/components/ChatSearchResults.js
Normal file
@ -0,0 +1,72 @@
|
||||
import { LitElement, html } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
import { chatSearchResultsStyles } from './ChatSearchResults-css.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
import '@vaadin/icon'
|
||||
import '@vaadin/icons'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
export class ChatSearchResults extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
onClickFunc: { attribute: false },
|
||||
closeFunc: { attribute: false },
|
||||
searchResults: { type: Array },
|
||||
isOpen: { type: Boolean },
|
||||
loading: { type: Boolean }
|
||||
}
|
||||
}
|
||||
|
||||
static styles = [chatSearchResultsStyles]
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="chat-results-card" style=${this.isOpen ? "display: block;" : "display: none;"}>
|
||||
<vaadin-icon
|
||||
@click=${() => this.closeFunc()}
|
||||
icon="vaadin:close-small"
|
||||
slot="icon"
|
||||
class="close-icon"
|
||||
>
|
||||
</vaadin-icon>
|
||||
${this.loading ? (
|
||||
html`
|
||||
<div class="spinner-container">
|
||||
<paper-spinner-lite active></paper-spinner-lite>
|
||||
</div>
|
||||
`
|
||||
) : (
|
||||
html`
|
||||
<p class="chat-result-header">${translate("chatpage.cchange36")}</p>
|
||||
<div class="divider"></div>
|
||||
<div class="chat-result-container">
|
||||
${this.searchResults.length === 0 ? (
|
||||
html`<p class="no-results">${translate("chatpage.cchange37")}</p>`
|
||||
) : (
|
||||
html`
|
||||
${this.searchResults.map((result) => {
|
||||
return (
|
||||
html`
|
||||
<div class="chat-result-card" @click=${() => {
|
||||
this.shadowRoot.querySelector(".chat-result-card").classList.add("active");
|
||||
this.onClickFunc(result);
|
||||
}}>
|
||||
<p class="chat-result">
|
||||
${result.name}
|
||||
</p>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
)}
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
customElements.define('chat-search-results', ChatSearchResults)
|
@ -1,4 +1,5 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
|
||||
import '@material/mwc-icon'
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
import '@material/mwc-icon'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
@ -176,7 +177,7 @@ class ChatSideNavHeads extends LitElement {
|
||||
this.config = JSON.parse(c)
|
||||
})
|
||||
})
|
||||
parentEpml.imReady();
|
||||
parentEpml.imReady()
|
||||
}
|
||||
|
||||
shouldUpdate(changedProperties) {
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { get } from 'lit-translate';
|
||||
import { escape, unescape } from 'html-escaper';
|
||||
import { EmojiPicker } from 'emoji-picker-js';
|
||||
import { inputKeyCodes } from '../../utils/keyCodes.js';
|
||||
import { Epml } from '../../../epml.js';
|
||||
import { LitElement, html, css } from "lit"
|
||||
import { escape, unescape } from 'html-escaper'
|
||||
import { EmojiPicker } from 'emoji-picker-js'
|
||||
import { inputKeyCodes } from '../../utils/keyCodes.js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
|
||||
class ChatTextEditor extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
@ -298,13 +299,13 @@ class ChatTextEditor extends LitElement {
|
||||
}
|
||||
|
||||
window.addEventListener('storage', () => {
|
||||
const checkTheme = localStorage.getItem('qortalTheme');
|
||||
const chatbar = this.shadowRoot.getElementById(this.iframeId).contentWindow.document.getElementById('chatbarId');
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
const chatbar = this.shadowRoot.getElementById(this.iframeId).contentWindow.document.getElementById('chatbarId')
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark';
|
||||
this.theme = 'dark'
|
||||
chatbar.style.cssText = "color:#ffffff;"
|
||||
} else {
|
||||
this.theme = 'light';
|
||||
this.theme = 'light'
|
||||
chatbar.style.cssText = "color:#080808;"
|
||||
}
|
||||
})
|
||||
@ -323,18 +324,18 @@ class ChatTextEditor extends LitElement {
|
||||
boxShadow: 'rgba(4, 4, 5, 0.15) 0px 0px 0px 1px, rgba(0, 0, 0, 0.24) 0px 8px 16px 0px',
|
||||
zIndex: 100
|
||||
|
||||
});
|
||||
})
|
||||
|
||||
this.emojiPicker.on('emoji', selection => {
|
||||
const emojiHtmlString = `<img class="emoji" draggable="false" alt="${selection.emoji}" src="${selection.url}">`;
|
||||
const emojiHtmlString = `<img class="emoji" draggable="false" alt="${selection.emoji}" src="${selection.url}">`
|
||||
this.chatEditor.insertEmoji(emojiHtmlString);
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
this.emojiPickerHandler.addEventListener('click', () => this.emojiPicker.togglePicker(this.emojiPickerHandler));
|
||||
this.emojiPickerHandler.addEventListener('click', () => this.emojiPicker.togglePicker(this.emojiPickerHandler))
|
||||
|
||||
await this.updateComplete;
|
||||
this.initChatEditor();
|
||||
await this.updateComplete
|
||||
this.initChatEditor()
|
||||
}
|
||||
|
||||
async updated(changedProperties) {
|
||||
@ -348,12 +349,12 @@ class ChatTextEditor extends LitElement {
|
||||
}
|
||||
}
|
||||
if (changedProperties && changedProperties.has('placeholder')) {
|
||||
const captionEditor = this.shadowRoot.getElementById(this.iframeId).contentWindow.document.getElementById('chatbarId');
|
||||
captionEditor.setAttribute('data-placeholder', this.placeholder);
|
||||
const captionEditor = this.shadowRoot.getElementById(this.iframeId).contentWindow.document.getElementById('chatbarId')
|
||||
captionEditor.setAttribute('data-placeholder', this.placeholder)
|
||||
}
|
||||
|
||||
if (changedProperties && changedProperties.has("imageFile")) {
|
||||
this.chatMessageInput = "newChat";
|
||||
this.chatMessageInput = "newChat"
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,12 +366,12 @@ class ChatTextEditor extends LitElement {
|
||||
|
||||
sendMessageFunc(props) {
|
||||
if (this.chatMessageSize > 1000 ) {
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange29"));
|
||||
return;
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange29"))
|
||||
return
|
||||
};
|
||||
this.chatMessageSize = 0;
|
||||
this.chatEditor.updateMirror();
|
||||
this._sendMessage(props);
|
||||
this.chatMessageSize = 0
|
||||
this.chatEditor.updateMirror()
|
||||
this._sendMessage(props)
|
||||
}
|
||||
|
||||
getMessageSize(message){
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { get, translate } from 'lit-translate';
|
||||
|
||||
import { EmojiPicker } from 'emoji-picker-js';
|
||||
import { Epml } from '../../../epml.js';
|
||||
import { render } from 'lit/html.js'
|
||||
import { EmojiPicker } from 'emoji-picker-js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-checkbox'
|
||||
// import { addAutoLoadImageChat } from "../../../../qortal-ui-core/src/redux/app/app-actions.js";
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
|
||||
class ChatTextEditor extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
@ -589,11 +589,11 @@ mwc-checkbox::shadow .mdc-checkbox::after, mwc-checkbox::shadow .mdc-checkbox::b
|
||||
const checkTheme = localStorage.getItem('qortalTheme');
|
||||
const chatbar = this.shadowRoot.querySelector('.element')
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark';
|
||||
this.theme = 'dark'
|
||||
chatbar.style.cssText = "color:#ffffff;"
|
||||
|
||||
} else {
|
||||
this.theme = 'light';
|
||||
this.theme = 'light'
|
||||
chatbar.style.cssText = "color:#080808;"
|
||||
|
||||
}
|
||||
|
@ -2,10 +2,7 @@ import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
registerTranslateConfig({
|
||||
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
|
||||
})
|
||||
import isElectron from 'is-electron'
|
||||
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-button'
|
||||
@ -13,6 +10,10 @@ import '@material/mwc-dialog'
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@vaadin/grid'
|
||||
|
||||
registerTranslateConfig({
|
||||
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
|
||||
})
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class ChatWelcomePage extends LitElement {
|
||||
@ -258,10 +259,16 @@ class ChatWelcomePage extends LitElement {
|
||||
|
||||
firstUpdated() {
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
|
||||
const stopKeyEventPropagation = (e) => {
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
e.stopPropagation()
|
||||
return false
|
||||
}
|
||||
|
||||
this.shadowRoot.getElementById('sendTo').addEventListener('keydown', stopKeyEventPropagation);
|
||||
@ -290,8 +297,6 @@ class ChatWelcomePage extends LitElement {
|
||||
document.querySelector('html').setAttribute('theme', this.theme)
|
||||
})
|
||||
|
||||
let configLoaded = false
|
||||
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe('selected_address', async selectedAddress => {
|
||||
this.selectedAddress = {}
|
||||
@ -309,19 +314,26 @@ class ChatWelcomePage extends LitElement {
|
||||
parentEpml.imReady()
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark';
|
||||
this.theme = 'dark'
|
||||
} else {
|
||||
this.theme = 'light';
|
||||
this.theme = 'light'
|
||||
}
|
||||
document.querySelector('html').setAttribute('theme', this.theme);
|
||||
document.querySelector('html').setAttribute('theme', this.theme)
|
||||
}
|
||||
|
||||
changeLanguage() {
|
||||
const checkLanguage = localStorage.getItem('qortalLanguage')
|
||||
|
||||
if (checkLanguage === null || checkLanguage.length === 0) {
|
||||
localStorage.setItem('qortalLanguage', 'us')
|
||||
use('us')
|
||||
@ -343,7 +355,7 @@ class ChatWelcomePage extends LitElement {
|
||||
} else {
|
||||
this.sendMessage();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async sendMessage() {
|
||||
this.isLoading = true;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { translate, get } from 'lit-translate';
|
||||
import { render } from 'lit/html.js';
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
export class ImageComponent extends LitElement {
|
||||
|
||||
@ -48,52 +48,51 @@ border: 1px solid var(--mdc-theme-primary );
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.attempts = 0;
|
||||
this.maxAttempts = 5;
|
||||
super()
|
||||
this.attempts = 0
|
||||
this.maxAttempts = 5
|
||||
}
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
let apiKey = myNode.apiKey
|
||||
return apiKey
|
||||
}
|
||||
|
||||
async _fetchImage() {
|
||||
this.attempts++;
|
||||
if (this.attempts > this.maxAttempts) return;
|
||||
if (this.attempts > this.maxAttempts) return
|
||||
await new Promise((res) => {
|
||||
setTimeout(() => {
|
||||
res();
|
||||
res()
|
||||
}, 1000)
|
||||
});
|
||||
})
|
||||
try {
|
||||
const response = await fetch(this.gif.url);
|
||||
const data = await response.json();
|
||||
console.log({data});
|
||||
const response = await fetch(this.gif.url)
|
||||
const data = await response.json()
|
||||
if (data.ok) {
|
||||
this.error = false;
|
||||
this.error = false
|
||||
this.gif = {
|
||||
...this.gif,
|
||||
url: data.src
|
||||
};
|
||||
this.requestUpdate();
|
||||
} else if (!data.ok || data.error) {
|
||||
this.error = true;
|
||||
this.error = true
|
||||
} else {
|
||||
this.error = false;
|
||||
this.error = false
|
||||
}
|
||||
} catch (error) {
|
||||
this.error = true;
|
||||
console.error(error);
|
||||
this._fetchImage();
|
||||
this.error = true
|
||||
console.error(error)
|
||||
this._fetchImage()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.error && this.attempts <= this.maxAttempts) {
|
||||
setTimeout(() => {
|
||||
this._fetchImage();
|
||||
}, 1000);
|
||||
this._fetchImage()
|
||||
}, 1000)
|
||||
}
|
||||
return html`
|
||||
${this.gif && !this.error
|
||||
@ -124,4 +123,4 @@ alt=${this.alt}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('image-component', ImageComponent);
|
||||
customElements.define('image-component', ImageComponent)
|
||||
|
@ -3,11 +3,6 @@ import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
import snackbar from './snackbar.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
registerTranslateConfig({
|
||||
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
|
||||
})
|
||||
|
||||
import '@polymer/paper-tooltip/paper-tooltip.js'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
@ -15,8 +10,8 @@ const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
class LevelFounder extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
checkleveladdress: { type: String, attribute: true },
|
||||
selectedAddress: { type: Object },
|
||||
checkleveladdress: { type: String },
|
||||
selectedAddress: { type: String },
|
||||
config: { type: Object },
|
||||
memberInfo: { type: Array }
|
||||
}
|
||||
@ -106,16 +101,8 @@ class LevelFounder extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.changeLanguage()
|
||||
this.checkAddressInfo()
|
||||
|
||||
window.addEventListener('storage', () => {
|
||||
const checkLanguage = localStorage.getItem('qortalLanguage')
|
||||
use(checkLanguage)
|
||||
})
|
||||
|
||||
let configLoaded = false
|
||||
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe('selected_address', async selectedAddress => {
|
||||
this.selectedAddress = {}
|
||||
@ -127,17 +114,6 @@ class LevelFounder extends LitElement {
|
||||
parentEpml.imReady()
|
||||
}
|
||||
|
||||
changeLanguage() {
|
||||
const checkLanguage = localStorage.getItem('qortalLanguage')
|
||||
|
||||
if (checkLanguage === null || checkLanguage.length === 0) {
|
||||
localStorage.setItem('qortalLanguage', 'us')
|
||||
use('us')
|
||||
} else {
|
||||
use(checkLanguage)
|
||||
}
|
||||
}
|
||||
|
||||
async checkAddressInfo() {
|
||||
let toCheck = this.checkleveladdress
|
||||
const memberInfo = await parentEpml.request('apiCall', {
|
||||
@ -147,23 +123,23 @@ class LevelFounder extends LitElement {
|
||||
}
|
||||
|
||||
renderFounder() {
|
||||
let adressfounder = this.memberInfo.flags;
|
||||
let adressfounder = this.memberInfo.flags
|
||||
if (adressfounder === 1) {
|
||||
return html `
|
||||
<span id="founderTooltip" class="badge">F</span>
|
||||
<paper-tooltip class="custom" for="founderTooltip" position="top">FOUNDER</paper-tooltip>
|
||||
`
|
||||
} else {
|
||||
return null;
|
||||
return html ``
|
||||
}
|
||||
}
|
||||
|
||||
renderLevel() {
|
||||
let adresslevel = this.memberInfo.level;
|
||||
let adresslevel = this.memberInfo.level
|
||||
return adresslevel ? html `
|
||||
<img id="level-img" src=${`/img/badges/level-${adresslevel}.png`} alt=${`badge-${adresslevel}`} class="message-data-level" />
|
||||
<paper-tooltip class="level-img-tooltip" for="level-img" position="top" >
|
||||
${translate("mintingpage.mchange27")} ${adresslevel}
|
||||
${translate("mintingpage.mchange27")} ${adresslevel}
|
||||
</paper-tooltip>
|
||||
` : ''
|
||||
}
|
||||
@ -174,9 +150,9 @@ class LevelFounder extends LitElement {
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
let apiKey = myNode.apiKey
|
||||
return apiKey
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,6 @@ import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../epml.js'
|
||||
import snackbar from './snackbar.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
registerTranslateConfig({
|
||||
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
|
||||
})
|
||||
|
||||
import '@material/mwc-snackbar'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
@ -250,17 +245,12 @@ class NameMenu extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.getChatBlockedAdresses();
|
||||
this.getChatBlockedAdresses()
|
||||
|
||||
setInterval(() => {
|
||||
this.getChatBlockedAdresses();
|
||||
this.getChatBlockedAdresses()
|
||||
}, 60000)
|
||||
|
||||
window.addEventListener('storage', () => {
|
||||
const checkLanguage = localStorage.getItem('qortalLanguage');
|
||||
use(checkLanguage);
|
||||
})
|
||||
|
||||
window.onclick = function(event) {
|
||||
if (!event.target.matches('.block')) {
|
||||
var dropdowns = document.getElementsByClassName('dropdown-content');
|
||||
@ -275,12 +265,12 @@ class NameMenu extends LitElement {
|
||||
}
|
||||
|
||||
const stopKeyEventPropagation = (e) => {
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
e.stopPropagation()
|
||||
return false
|
||||
}
|
||||
|
||||
this.shadowRoot.getElementById('sendTo').addEventListener('keydown', stopKeyEventPropagation);
|
||||
this.shadowRoot.getElementById('messageBox').addEventListener('keydown', stopKeyEventPropagation);
|
||||
this.shadowRoot.getElementById('sendTo').addEventListener('keydown', stopKeyEventPropagation)
|
||||
this.shadowRoot.getElementById('messageBox').addEventListener('keydown', stopKeyEventPropagation)
|
||||
|
||||
const getDataFromURL = () => {
|
||||
let tempUrl = document.location.href
|
||||
@ -309,17 +299,6 @@ class NameMenu extends LitElement {
|
||||
parentEpml.imReady()
|
||||
}
|
||||
|
||||
changeLanguage() {
|
||||
const checkLanguage = localStorage.getItem('qortalLanguage')
|
||||
|
||||
if (checkLanguage === null || checkLanguage.length === 0) {
|
||||
localStorage.setItem('qortalLanguage', 'us')
|
||||
use('us')
|
||||
} else {
|
||||
use(checkLanguage)
|
||||
}
|
||||
}
|
||||
|
||||
myMenu() {
|
||||
this.shadowRoot.getElementById('myDropdown').classList.toggle('showList')
|
||||
this.shadowRoot.querySelector('#blockNameDialog').close()
|
||||
|
@ -24,11 +24,11 @@ class TimeAgo extends LitElement {
|
||||
}
|
||||
});
|
||||
|
||||
this.shadowRoot.querySelector('time-ago').setAttribute('title', '');
|
||||
this.shadowRoot.querySelector('time-ago').setAttribute('title', '')
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
super()
|
||||
this.timestamp = 0
|
||||
this.timeIso = ''
|
||||
this.format = ''
|
||||
@ -41,7 +41,7 @@ class TimeAgo extends LitElement {
|
||||
}
|
||||
|
||||
renderTime(timestamp) {
|
||||
timestamp === undefined ? this.timeIso = '' : this.timeIso = new Date(timestamp).toISOString();
|
||||
timestamp === undefined ? this.timeIso = '' : this.timeIso = new Date(timestamp).toISOString()
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { LitElement, html } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { get, translate } from 'lit-translate';
|
||||
import { tipUserStyles } from './TipUser-css.js';
|
||||
import { Epml } from '../../../epml';
|
||||
import '@vaadin/button';
|
||||
import '@polymer/paper-progress/paper-progress.js';
|
||||
import { LitElement, html } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { tipUserStyles } from './TipUser-css.js'
|
||||
import { Epml } from '../../../epml'
|
||||
import '@vaadin/button'
|
||||
import '@polymer/paper-progress/paper-progress.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
const parentEpml = new Epml({ type: "WINDOW", source: window.parent });
|
||||
|
||||
@ -34,15 +34,15 @@ export class TipUser extends LitElement {
|
||||
static styles = [tipUserStyles]
|
||||
|
||||
async firstUpdated() {
|
||||
await this.fetchWalletDetails();
|
||||
await this.fetchWalletDetails()
|
||||
}
|
||||
|
||||
updated(changedProperties) {
|
||||
if (changedProperties && changedProperties.has("closeTipUser")) {
|
||||
if (this.closeTipUser) {
|
||||
this.shadowRoot.getElementById("amountInput").value = "";
|
||||
this.errorMessage = "";
|
||||
this.successMessage = "";
|
||||
this.shadowRoot.getElementById("amountInput").value = ""
|
||||
this.errorMessage = ""
|
||||
this.successMessage = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -52,7 +52,7 @@ export class TipUser extends LitElement {
|
||||
type: "api",
|
||||
url: `/addresses/lastreference/${this.myAddress.address}`,
|
||||
})
|
||||
return myRef;
|
||||
return myRef
|
||||
}
|
||||
|
||||
renderSuccessText() {
|
||||
@ -64,9 +64,9 @@ export class TipUser extends LitElement {
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
let apiKey = myNode.apiKey
|
||||
return apiKey
|
||||
}
|
||||
|
||||
async fetchWalletDetails() {
|
||||
@ -78,85 +78,85 @@ export class TipUser extends LitElement {
|
||||
let snack4string = get("chatpage.cchange48")
|
||||
parentEpml.request('showSnackBar', `${snack4string}`)
|
||||
} else {
|
||||
this.walletBalance = Number(res).toFixed(8);
|
||||
this.walletBalance = Number(res).toFixed(8)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async sendQort() {
|
||||
const amount = this.shadowRoot.getElementById("amountInput").value;
|
||||
let recipient = this.userName;
|
||||
this.sendMoneyLoading = true;
|
||||
this.btnDisable = true;
|
||||
const amount = this.shadowRoot.getElementById("amountInput").value
|
||||
let recipient = this.userName
|
||||
this.sendMoneyLoading = true
|
||||
this.btnDisable = true
|
||||
|
||||
if (parseFloat(amount) + parseFloat(0.001) > parseFloat(this.walletBalance)) {
|
||||
this.sendMoneyLoading = false;
|
||||
this.btnDisable = false;
|
||||
let snack1string = get("chatpage.cchange51");
|
||||
parentEpml.request('showSnackBar', `${snack1string}`);
|
||||
return false;
|
||||
this.sendMoneyLoading = false
|
||||
this.btnDisable = false
|
||||
let snack1string = get("chatpage.cchange51")
|
||||
parentEpml.request('showSnackBar', `${snack1string}`)
|
||||
return false
|
||||
}
|
||||
|
||||
if (parseFloat(amount) <= 0) {
|
||||
this.sendMoneyLoading = false;
|
||||
this.btnDisable = false;
|
||||
let snack2string = get("chatpage.cchange52");
|
||||
parentEpml.request('showSnackBar', `${snack2string}`);
|
||||
return false;
|
||||
this.sendMoneyLoading = false
|
||||
this.btnDisable = false
|
||||
let snack2string = get("chatpage.cchange52")
|
||||
parentEpml.request('showSnackBar', `${snack2string}`)
|
||||
return false
|
||||
}
|
||||
|
||||
if (recipient.length === 0) {
|
||||
this.sendMoneyLoading = false;
|
||||
this.btnDisable = false;
|
||||
let snack3string = get("chatpage.cchange53");
|
||||
parentEpml.request('showSnackBar', `${snack3string}`);
|
||||
return false;
|
||||
this.sendMoneyLoading = false
|
||||
this.btnDisable = false
|
||||
let snack3string = get("chatpage.cchange53")
|
||||
parentEpml.request('showSnackBar', `${snack3string}`)
|
||||
return false
|
||||
}
|
||||
|
||||
const validateName = async (receiverName) => {
|
||||
let myRes;
|
||||
let myRes
|
||||
let myNameRes = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/names/${receiverName}`,
|
||||
})
|
||||
|
||||
if (myNameRes.error === 401) {
|
||||
myRes = false;
|
||||
myRes = false
|
||||
} else {
|
||||
myRes = myNameRes;
|
||||
myRes = myNameRes
|
||||
}
|
||||
return myRes;
|
||||
}
|
||||
|
||||
const validateAddress = async (receiverAddress) => {
|
||||
let myAddress = await window.parent.validateAddress(receiverAddress);
|
||||
return myAddress;
|
||||
let myAddress = await window.parent.validateAddress(receiverAddress)
|
||||
return myAddress
|
||||
}
|
||||
|
||||
const validateReceiver = async (recipient) => {
|
||||
let lastRef = await this.getLastRef();
|
||||
let isAddress;
|
||||
let lastRef = await this.getLastRef()
|
||||
let isAddress
|
||||
|
||||
try {
|
||||
isAddress = await validateAddress(recipient);
|
||||
isAddress = await validateAddress(recipient)
|
||||
} catch (err) {
|
||||
isAddress = false;
|
||||
isAddress = false
|
||||
}
|
||||
|
||||
if (isAddress) {
|
||||
let myTransaction = await makeTransactionRequest(recipient, lastRef);
|
||||
getTxnRequestResponse(myTransaction);
|
||||
let myTransaction = await makeTransactionRequest(recipient, lastRef)
|
||||
getTxnRequestResponse(myTransaction)
|
||||
} else {
|
||||
let myNameRes = await validateName(recipient);
|
||||
let myNameRes = await validateName(recipient)
|
||||
if (myNameRes !== false) {
|
||||
let myNameAddress = myNameRes.owner
|
||||
let myTransaction = await makeTransactionRequest(myNameAddress, lastRef)
|
||||
getTxnRequestResponse(myTransaction)
|
||||
} else {
|
||||
console.error(this.renderReceiverText())
|
||||
this.errorMessage = this.renderReceiverText();
|
||||
this.sendMoneyLoading = false;
|
||||
this.btnDisable = false;
|
||||
this.errorMessage = this.renderReceiverText()
|
||||
this.sendMoneyLoading = false
|
||||
this.btnDisable = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,23 +169,23 @@ export class TipUser extends LitElement {
|
||||
});
|
||||
|
||||
if (getNames?.length > 0 ) {
|
||||
return getNames[0].name;
|
||||
return getNames[0].name
|
||||
} else {
|
||||
return '';
|
||||
return ''
|
||||
}
|
||||
} catch (error) {
|
||||
return "";
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
const makeTransactionRequest = async (receiver, lastRef) => {
|
||||
let myReceiver = receiver;
|
||||
let mylastRef = lastRef;
|
||||
let dialogamount = get("transactions.amount");
|
||||
let dialogAddress = get("login.address");
|
||||
let dialogName = get("login.name");
|
||||
let dialogto = get("transactions.to");
|
||||
let recipientName = await getName(myReceiver);
|
||||
let myReceiver = receiver
|
||||
let mylastRef = lastRef
|
||||
let dialogamount = get("transactions.amount")
|
||||
let dialogAddress = get("login.address")
|
||||
let dialogName = get("login.name")
|
||||
let dialogto = get("transactions.to")
|
||||
let recipientName = await getName(myReceiver)
|
||||
let myTxnrequest = await parentEpml.request('transaction', {
|
||||
type: 2,
|
||||
nonce: this.myAddress.nonce,
|
||||
@ -201,33 +201,33 @@ export class TipUser extends LitElement {
|
||||
dialogName
|
||||
},
|
||||
})
|
||||
return myTxnrequest;
|
||||
return myTxnrequest
|
||||
}
|
||||
|
||||
const getTxnRequestResponse = (txnResponse) => {
|
||||
if (txnResponse.success === false && txnResponse.message) {
|
||||
this.errorMessage = txnResponse.message;
|
||||
this.sendMoneyLoading = false;
|
||||
this.btnDisable = false;
|
||||
throw new Error(txnResponse);
|
||||
this.errorMessage = txnResponse.message
|
||||
this.sendMoneyLoading = false
|
||||
this.btnDisable = false
|
||||
throw new Error(txnResponse)
|
||||
} else if (txnResponse.success === true && !txnResponse.data.error) {
|
||||
this.shadowRoot.getElementById('amountInput').value = '';
|
||||
this.errorMessage = '';
|
||||
this.successMessage = this.renderSuccessText();
|
||||
this.sendMoneyLoading = false;
|
||||
this.btnDisable = false;
|
||||
this.shadowRoot.getElementById('amountInput').value = ''
|
||||
this.errorMessage = ''
|
||||
this.successMessage = this.renderSuccessText()
|
||||
this.sendMoneyLoading = false
|
||||
this.btnDisable = false
|
||||
setTimeout(() => {
|
||||
this.setOpenTipUser(false);
|
||||
this.successMessage = "";
|
||||
}, 3000);
|
||||
this.setOpenTipUser(false)
|
||||
this.successMessage = ""
|
||||
}, 3000)
|
||||
} else {
|
||||
this.errorMessage = txnResponse.data.message;
|
||||
this.sendMoneyLoading = false;
|
||||
this.btnDisable = false;
|
||||
throw new Error(txnResponse);
|
||||
this.errorMessage = txnResponse.data.message
|
||||
this.sendMoneyLoading = false
|
||||
this.btnDisable = false
|
||||
throw new Error(txnResponse)
|
||||
}
|
||||
}
|
||||
validateReceiver(recipient);
|
||||
validateReceiver(recipient)
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -274,4 +274,4 @@ export class TipUser extends LitElement {
|
||||
`;
|
||||
}
|
||||
}
|
||||
customElements.define('tip-user', TipUser);
|
||||
customElements.define('tip-user', TipUser)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { Epml } from '../../../epml.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
|
@ -1,119 +1,110 @@
|
||||
import { LitElement, html } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { translate } from 'lit-translate';
|
||||
import { userInfoStyles } from './UserInfo-css.js';
|
||||
import { Epml } from '../../../../epml';
|
||||
import '@vaadin/button';
|
||||
import '@polymer/paper-progress/paper-progress.js';
|
||||
import { cropAddress } from '../../../utils/cropAddress.js';
|
||||
import { LitElement, html } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
import { userInfoStyles } from './UserInfo-css.js'
|
||||
import { Epml } from '../../../../epml'
|
||||
import { cropAddress } from '../../../utils/cropAddress.js'
|
||||
|
||||
import '@polymer/paper-progress/paper-progress.js'
|
||||
import '@vaadin/button'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
export class UserInfo extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
setOpenUserInfo: { attribute: false },
|
||||
setOpenTipUser: { attribute: false },
|
||||
setOpenPrivateMessage: { attribute: false },
|
||||
userName: { type: String },
|
||||
selectedHead: { type: Object },
|
||||
isImageLoaded: { type: Boolean }
|
||||
static get properties() {
|
||||
return {
|
||||
setOpenUserInfo: { attribute: false },
|
||||
setOpenTipUser: { attribute: false },
|
||||
setOpenPrivateMessage: { attribute: false },
|
||||
userName: { type: String },
|
||||
selectedHead: { type: Object },
|
||||
isImageLoaded: { type: Boolean }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.isImageLoaded = false
|
||||
this.selectedHead = {}
|
||||
this.imageFetches = 0
|
||||
constructor() {
|
||||
super()
|
||||
this.isImageLoaded = false
|
||||
this.selectedHead = {}
|
||||
this.imageFetches = 0
|
||||
}
|
||||
|
||||
static styles = [userInfoStyles]
|
||||
|
||||
createImage(imageUrl) {
|
||||
const imageHTMLRes = new Image()
|
||||
imageHTMLRes.src = imageUrl
|
||||
imageHTMLRes.classList.add("user-info-avatar")
|
||||
imageHTMLRes.onload = () => {
|
||||
this.isImageLoaded = true
|
||||
}
|
||||
imageHTMLRes.onerror = () => {
|
||||
if (this.imageFetches < 4) {
|
||||
setTimeout(() => {
|
||||
this.imageFetches = this.imageFetches + 1
|
||||
imageHTMLRes.src = imageUrl;
|
||||
}, 10000)
|
||||
} else {
|
||||
this.isImageLoaded = false
|
||||
}
|
||||
}
|
||||
return imageHTMLRes
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
let avatarImg = ""
|
||||
if (this.selectedHead && this.selectedHead.name) {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
const avatarUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${this.selectedHead.name}/qortal_avatar?async=true&apiKey=${myNode.apiKey}`
|
||||
avatarImg = this.createImage(avatarUrl)
|
||||
}
|
||||
return html`
|
||||
<div style="position: relative;">
|
||||
<vaadin-icon
|
||||
class="close-icon"
|
||||
icon="vaadin:close-big"
|
||||
slot="icon"
|
||||
@click=${() => {
|
||||
this.setOpenUserInfo(false)
|
||||
}}
|
||||
>
|
||||
</vaadin-icon>
|
||||
${this.isImageLoaded ? html`<div class="avatar-container">${avatarImg}</div>` : html``}
|
||||
${!this.isImageLoaded && this.selectedHead && this.selectedHead.name ? html`
|
||||
<div class="avatar-container">
|
||||
<div class="user-info-no-avatar">
|
||||
${this.selectedHead.name.charAt(0)}
|
||||
</div>
|
||||
</div>
|
||||
` : ""}
|
||||
${!this.isImageLoaded && this.selectedHead && !this.selectedHead.name ? html`
|
||||
<div class="avatar-container">
|
||||
<img src="/img/incognito.png" alt="avatar" />
|
||||
</div>`
|
||||
: ""}
|
||||
<div class="user-info-header">
|
||||
${this.selectedHead && this.selectedHead.name ? this.selectedHead.name : this.selectedHead ? cropAddress(this.selectedHead.address) : null}
|
||||
</div>
|
||||
<div class="send-message-button" @click="${() => {
|
||||
this.setOpenPrivateMessage({
|
||||
name: this.userName,
|
||||
open: true
|
||||
})
|
||||
this.setOpenUserInfo(false)
|
||||
}}">
|
||||
${translate("chatpage.cchange58")}
|
||||
</div>
|
||||
<div style="margin-top: 5px;" class="send-message-button" @click=${() => {
|
||||
this.setOpenTipUser(true)
|
||||
this.setOpenUserInfo(false)
|
||||
}}>
|
||||
${translate("chatpage.cchange59")}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
static styles = [userInfoStyles]
|
||||
|
||||
createImage(imageUrl) {
|
||||
const imageHTMLRes = new Image();
|
||||
imageHTMLRes.src = imageUrl;
|
||||
imageHTMLRes.classList.add("user-info-avatar");
|
||||
imageHTMLRes.onload = () => {
|
||||
this.isImageLoaded = true;
|
||||
}
|
||||
imageHTMLRes.onerror = () => {
|
||||
if (this.imageFetches < 4) {
|
||||
setTimeout(() => {
|
||||
this.imageFetches = this.imageFetches + 1;
|
||||
imageHTMLRes.src = imageUrl;
|
||||
}, 500);
|
||||
} else {
|
||||
this.isImageLoaded = false
|
||||
}
|
||||
};
|
||||
return imageHTMLRes;
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
let avatarImg = "";
|
||||
if (this.selectedHead && this.selectedHead.name) {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
const avatarUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${this.selectedHead.name}/qortal_avatar?async=true&apiKey=${myNode.apiKey}`;
|
||||
avatarImg = this.createImage(avatarUrl);
|
||||
}
|
||||
return html`
|
||||
<div style=${"position: relative;"}>
|
||||
<vaadin-icon
|
||||
class="close-icon"
|
||||
icon="vaadin:close-big"
|
||||
slot="icon"
|
||||
@click=${() => {
|
||||
this.setOpenUserInfo(false)
|
||||
}}>
|
||||
</vaadin-icon>
|
||||
${this.isImageLoaded ?
|
||||
html`
|
||||
<div class="avatar-container">
|
||||
${avatarImg}
|
||||
</div>` :
|
||||
html``}
|
||||
${!this.isImageLoaded && this.selectedHead && this.selectedHead.name ?
|
||||
html`
|
||||
<div class="avatar-container">
|
||||
<div class="user-info-no-avatar">
|
||||
${this.selectedHead.name.charAt(0)}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
${!this.isImageLoaded && this.selectedHead && !this.selectedHead.name ?
|
||||
html`
|
||||
<div class="avatar-container">
|
||||
<img src="/img/incognito.png" alt="avatar" />
|
||||
</div>`
|
||||
: ""}
|
||||
<div class="user-info-header">
|
||||
${this.selectedHead && this.selectedHead.name ? this.selectedHead.name : this.selectedHead ? cropAddress(this.selectedHead.address) : null}
|
||||
</div>
|
||||
<div
|
||||
class="send-message-button"
|
||||
@click="${() => {
|
||||
this.setOpenPrivateMessage({
|
||||
name: this.userName,
|
||||
open: true
|
||||
})
|
||||
this.setOpenUserInfo(false);
|
||||
}
|
||||
}">
|
||||
${translate("chatpage.cchange58")}
|
||||
</div>
|
||||
<div
|
||||
style=${"margin-top: 5px;"}
|
||||
class="send-message-button"
|
||||
@click=${() => {
|
||||
this.setOpenTipUser(true);
|
||||
this.setOpenUserInfo(false);
|
||||
}}>
|
||||
${translate("chatpage.cchange59")}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
customElements.define('user-info', UserInfo);
|
||||
customElements.define('user-info', UserInfo)
|
||||
|
@ -1,33 +1,32 @@
|
||||
import { LitElement, html } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { LitElement, html } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { wrapperModalStyles } from './WrapperModal-css.js'
|
||||
|
||||
export class WrapperModal extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
customStyle: {type: String},
|
||||
onClickFunc: { attribute: false },
|
||||
zIndex: {type: Number}
|
||||
static get properties() {
|
||||
return {
|
||||
customStyle: {type: String},
|
||||
onClickFunc: { attribute: false },
|
||||
zIndex: {type: Number}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static styles = [wrapperModalStyles]
|
||||
static styles = [wrapperModalStyles]
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div>
|
||||
<div
|
||||
style="z-index: ${this.zIndex || 50}"
|
||||
class="backdrop"
|
||||
@click=${() => {
|
||||
this.onClickFunc();
|
||||
}}>
|
||||
</div>
|
||||
<div class="modal-body" style=${this.customStyle ? this.customStyle : ""}>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
render() {
|
||||
return html`
|
||||
<div>
|
||||
<div
|
||||
style="z-index: ${this.zIndex || 50}"
|
||||
class="backdrop"
|
||||
@click=${() => { this.onClickFunc() }}
|
||||
>
|
||||
</div>
|
||||
<div class="modal-body" style=${this.customStyle ? this.customStyle : ""}>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
customElements.define('wrapper-modal', WrapperModal);
|
||||
customElements.define('wrapper-modal', WrapperModal)
|
||||
|
@ -107,7 +107,217 @@ export const encryptData = ({ data64, recipientPublicKey }) => {
|
||||
recipientPublicKey
|
||||
}
|
||||
} catch (error) {
|
||||
console.log({ error })
|
||||
throw new Error("Error in encrypting data")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const encryptDataGroup = ({ data64, publicKeys }) => {
|
||||
const userPublicKey = window.parent.reduxStore.getState().app.selectedAddress.base58PublicKey
|
||||
let combinedPublicKeys = publicKeys
|
||||
if (userPublicKey) {
|
||||
combinedPublicKeys = [...publicKeys, userPublicKey]
|
||||
}
|
||||
|
||||
const publicKeysDuplicateFree = [...new Set(combinedPublicKeys)];
|
||||
const Uint8ArrayData = base64ToUint8Array(data64)
|
||||
|
||||
if (!(Uint8ArrayData instanceof Uint8Array)) {
|
||||
throw new Error("The Uint8ArrayData you've submitted is invalid")
|
||||
}
|
||||
|
||||
try {
|
||||
const privateKey = window.parent.reduxStore.getState().app.selectedAddress.keyPair.privateKey
|
||||
if (!privateKey) {
|
||||
throw new Error("Unable to retrieve keys")
|
||||
}
|
||||
|
||||
// Generate a random symmetric key for the message.
|
||||
const messageKey = new Uint8Array(32);
|
||||
window.crypto.getRandomValues(messageKey);
|
||||
|
||||
const nonce = new Uint8Array(24);
|
||||
window.crypto.getRandomValues(nonce);
|
||||
|
||||
// Encrypt the data with the symmetric key.
|
||||
const encryptedData = nacl.secretbox(Uint8ArrayData, nonce, messageKey);
|
||||
|
||||
// Generate a keyNonce outside of the loop.
|
||||
const keyNonce = new Uint8Array(24);
|
||||
window.crypto.getRandomValues(keyNonce);
|
||||
|
||||
// Encrypt the symmetric key for each recipient.
|
||||
let encryptedKeys = [];
|
||||
publicKeysDuplicateFree.forEach((recipientPublicKey) => {
|
||||
const publicKeyUnit8Array = window.parent.Base58.decode(recipientPublicKey)
|
||||
|
||||
const convertedPrivateKey = ed2curve.convertSecretKey(privateKey)
|
||||
const convertedPublicKey = ed2curve.convertPublicKey(publicKeyUnit8Array)
|
||||
|
||||
const sharedSecret = new Uint8Array(32)
|
||||
// the length of the sharedSecret will be 32 + 16
|
||||
// When you're encrypting data using nacl.secretbox, it's adding an authentication tag to the result, which is 16 bytes long. This tag is used for verifying the integrity and authenticity of the data when it is decrypted
|
||||
|
||||
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey)
|
||||
|
||||
// Encrypt the symmetric key with the shared secret.
|
||||
const encryptedKey = nacl.secretbox(messageKey, keyNonce, sharedSecret);
|
||||
|
||||
encryptedKeys.push(encryptedKey);
|
||||
});
|
||||
const str = "qortalGroupEncryptedData";
|
||||
const strEncoder = new TextEncoder();
|
||||
const strUint8Array = strEncoder.encode(str);
|
||||
|
||||
// Convert sender's public key to Uint8Array and add to the message
|
||||
const senderPublicKeyUint8Array = window.parent.Base58.decode(userPublicKey);
|
||||
|
||||
// Combine all data into a single Uint8Array.
|
||||
// Calculate size of combinedData
|
||||
let combinedDataSize = strUint8Array.length + nonce.length + keyNonce.length + senderPublicKeyUint8Array.length + encryptedData.length + 4;
|
||||
let encryptedKeysSize = 0;
|
||||
|
||||
encryptedKeys.forEach((key) => {
|
||||
encryptedKeysSize += key.length;
|
||||
});
|
||||
|
||||
combinedDataSize += encryptedKeysSize;
|
||||
|
||||
let combinedData = new Uint8Array(combinedDataSize);
|
||||
|
||||
combinedData.set(strUint8Array);
|
||||
combinedData.set(nonce, strUint8Array.length);
|
||||
combinedData.set(keyNonce, strUint8Array.length + nonce.length);
|
||||
combinedData.set(senderPublicKeyUint8Array, strUint8Array.length + nonce.length + keyNonce.length);
|
||||
combinedData.set(encryptedData, strUint8Array.length + nonce.length + keyNonce.length + senderPublicKeyUint8Array.length);
|
||||
|
||||
// Initialize offset for encryptedKeys
|
||||
let encryptedKeysOffset = strUint8Array.length + nonce.length + keyNonce.length + senderPublicKeyUint8Array.length + encryptedData.length;
|
||||
encryptedKeys.forEach((key) => {
|
||||
combinedData.set(key, encryptedKeysOffset);
|
||||
encryptedKeysOffset += key.length;
|
||||
});
|
||||
const countArray = new Uint8Array(new Uint32Array([publicKeysDuplicateFree.length]).buffer);
|
||||
combinedData.set(countArray, combinedData.length - 4);
|
||||
const uint8arrayToData64 = uint8ArrayToBase64(combinedData)
|
||||
return uint8arrayToData64;
|
||||
|
||||
} catch (error) {
|
||||
throw new Error("Error in encrypting data")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function uint8ArrayStartsWith(uint8Array, string) {
|
||||
const stringEncoder = new TextEncoder();
|
||||
const stringUint8Array = stringEncoder.encode(string);
|
||||
|
||||
if (uint8Array.length < stringUint8Array.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < stringUint8Array.length; i++) {
|
||||
if (uint8Array[i] !== stringUint8Array[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function decryptDeprecatedSingle(uint8Array, publicKey) {
|
||||
const combinedData = uint8Array
|
||||
const str = "qortalEncryptedData";
|
||||
const strEncoder = new TextEncoder();
|
||||
const strUint8Array = strEncoder.encode(str);
|
||||
|
||||
const strData = combinedData.slice(0, strUint8Array.length);
|
||||
const nonce = combinedData.slice(strUint8Array.length, strUint8Array.length + 24);
|
||||
const _encryptedData = combinedData.slice(strUint8Array.length + 24);
|
||||
|
||||
const privateKey = window.parent.reduxStore.getState().app.selectedAddress.keyPair.privateKey
|
||||
const _publicKey = window.parent.Base58.decode(publicKey)
|
||||
|
||||
if (!privateKey || !_publicKey) {
|
||||
|
||||
throw new Error("Unable to retrieve keys")
|
||||
}
|
||||
|
||||
const convertedPrivateKey = ed2curve.convertSecretKey(privateKey)
|
||||
const convertedPublicKey = ed2curve.convertPublicKey(_publicKey)
|
||||
const sharedSecret = new Uint8Array(32);
|
||||
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey)
|
||||
|
||||
const _chatEncryptionSeed = new window.parent.Sha256().process(sharedSecret).finish().result
|
||||
const _decryptedData = nacl.secretbox.open(_encryptedData, nonce, _chatEncryptionSeed)
|
||||
if (!_decryptedData) {
|
||||
throw new Error("Unable to decrypt")
|
||||
}
|
||||
const decryptedDataToBase64 = uint8ArrayToBase64(_decryptedData)
|
||||
return decryptedDataToBase64
|
||||
}
|
||||
|
||||
export function decryptGroupData(data64EncryptedData) {
|
||||
const allCombined = base64ToUint8Array(data64EncryptedData);
|
||||
const str = "qortalGroupEncryptedData";
|
||||
const strEncoder = new TextEncoder();
|
||||
const strUint8Array = strEncoder.encode(str);
|
||||
|
||||
// Extract the nonce
|
||||
const nonceStartPosition = strUint8Array.length;
|
||||
const nonceEndPosition = nonceStartPosition + 24; // Nonce is 24 bytes
|
||||
const nonce = allCombined.slice(nonceStartPosition, nonceEndPosition);
|
||||
|
||||
// Extract the shared keyNonce
|
||||
const keyNonceStartPosition = nonceEndPosition;
|
||||
const keyNonceEndPosition = keyNonceStartPosition + 24; // Nonce is 24 bytes
|
||||
const keyNonce = allCombined.slice(keyNonceStartPosition, keyNonceEndPosition);
|
||||
|
||||
// Extract the sender's public key
|
||||
const senderPublicKeyStartPosition = keyNonceEndPosition;
|
||||
const senderPublicKeyEndPosition = senderPublicKeyStartPosition + 32; // Public keys are 32 bytes
|
||||
const senderPublicKey = allCombined.slice(senderPublicKeyStartPosition, senderPublicKeyEndPosition);
|
||||
|
||||
// Calculate count first
|
||||
const countStartPosition = allCombined.length - 4; // 4 bytes before the end, since count is stored in Uint32 (4 bytes)
|
||||
const countArray = allCombined.slice(countStartPosition, countStartPosition + 4);
|
||||
const count = new Uint32Array(countArray.buffer)[0];
|
||||
|
||||
// Then use count to calculate encryptedData
|
||||
const encryptedDataStartPosition = senderPublicKeyEndPosition; // start position of encryptedData
|
||||
const encryptedDataEndPosition = allCombined.length - ((count * (32 + 16)) + 4);
|
||||
const encryptedData = allCombined.slice(encryptedDataStartPosition, encryptedDataEndPosition);
|
||||
|
||||
// Extract the encrypted keys
|
||||
// 32+16 = 48
|
||||
const combinedKeys = allCombined.slice(encryptedDataEndPosition, encryptedDataEndPosition + (count * 48));
|
||||
const privateKey = window.parent.reduxStore.getState().app.selectedAddress.keyPair.privateKey
|
||||
|
||||
if (!privateKey) {
|
||||
throw new Error("Unable to retrieve keys")
|
||||
}
|
||||
|
||||
const convertedPrivateKey = ed2curve.convertSecretKey(privateKey)
|
||||
const convertedSenderPublicKey = ed2curve.convertPublicKey(senderPublicKey)
|
||||
const sharedSecret = new Uint8Array(32)
|
||||
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedSenderPublicKey)
|
||||
for (let i = 0; i < count; i++) {
|
||||
const encryptedKey = combinedKeys.slice(i * 48, (i + 1) * 48);
|
||||
|
||||
// Decrypt the symmetric key.
|
||||
const decryptedKey = nacl.secretbox.open(encryptedKey, keyNonce, sharedSecret);
|
||||
|
||||
// If decryption was successful, decryptedKey will not be null.
|
||||
if (decryptedKey) {
|
||||
// Decrypt the data using the symmetric key.
|
||||
const decryptedData = nacl.secretbox.open(encryptedData, nonce, decryptedKey);
|
||||
|
||||
// If decryption was successful, decryptedData will not be null.
|
||||
if (decryptedData) {
|
||||
|
||||
return decryptedData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Unable to decrypt data")
|
||||
}
|
||||
|
@ -43,6 +43,9 @@ export const ENCRYPT_DATA = 'ENCRYPT_DATA'
|
||||
// DECRYPT_DATA
|
||||
export const DECRYPT_DATA = 'DECRYPT_DATA'
|
||||
|
||||
// DECRYPT_DATA_GROUP
|
||||
export const DECRYPT_DATA_GROUP = 'DECRYPT_DATA_GROUP'
|
||||
|
||||
// SAVE_FILE
|
||||
export const SAVE_FILE = 'SAVE_FILE'
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
import '@polymer/paper-dialog/paper-dialog.js'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-icon'
|
||||
|
@ -1849,6 +1849,18 @@ class GroupManagement extends LitElement {
|
||||
})
|
||||
})
|
||||
parentEpml.imReady()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { parentEpml } from './connect.js';
|
||||
import './streams/streams.js';
|
||||
|
||||
let config = {};
|
||||
let haveRegisteredNodeManagement = false;
|
||||
let config = {}
|
||||
let haveRegisteredNodeManagement = false
|
||||
|
||||
parentEpml.ready().then(() => {
|
||||
// pluginUrlsConf
|
||||
@ -186,20 +186,20 @@ parentEpml.ready().then(() => {
|
||||
];
|
||||
|
||||
const registerPlugins = (pluginInfo) => {
|
||||
parentEpml.request('registerUrl', pluginInfo);
|
||||
parentEpml.request('registerUrl', pluginInfo)
|
||||
};
|
||||
|
||||
const checkNode =
|
||||
window.parent.reduxStore.getState().app.nodeConfig.knownNodes[
|
||||
window.parent.reduxStore.getState().app.nodeConfig.node
|
||||
];
|
||||
]
|
||||
|
||||
parentEpml.subscribe('config', (c) => {
|
||||
config = JSON.parse(c);
|
||||
config = JSON.parse(c)
|
||||
|
||||
// Only register node management if node management is enabled and it hasn't already been registered
|
||||
if (!haveRegisteredNodeManagement && checkNode.enableManagement) {
|
||||
haveRegisteredNodeManagement = true;
|
||||
haveRegisteredNodeManagement = true
|
||||
|
||||
let nodeManagementConf = {
|
||||
url: 'node-management',
|
||||
@ -213,10 +213,10 @@ parentEpml.ready().then(() => {
|
||||
parent: false,
|
||||
};
|
||||
|
||||
let _pluginUrlsConf = [...pluginUrlsConf, nodeManagementConf];
|
||||
registerPlugins(_pluginUrlsConf);
|
||||
let _pluginUrlsConf = [...pluginUrlsConf, nodeManagementConf]
|
||||
registerPlugins(_pluginUrlsConf)
|
||||
} else {
|
||||
registerPlugins(pluginUrlsConf);
|
||||
registerPlugins(pluginUrlsConf)
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
@ -1,6 +1,10 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { Epml } from '../../../../epml.js'
|
||||
import isElectron from 'is-electron'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class ChainMessaging extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
@ -44,12 +48,18 @@ class ChainMessaging extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
|
||||
setInterval(() => {
|
||||
this.changeTheme();
|
||||
}, 100)
|
||||
window.addEventListener('storage', () => {
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark'
|
||||
} else {
|
||||
this.theme = 'light'
|
||||
}
|
||||
document.querySelector('html').setAttribute('theme', this.theme)
|
||||
})
|
||||
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
@ -60,6 +70,14 @@ class ChainMessaging extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
if (checkTheme === 'dark') {
|
||||
|
@ -138,13 +138,8 @@ class Messaging extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
|
||||
setInterval(() => {
|
||||
this.changeTheme();
|
||||
}, 100)
|
||||
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
window.addEventListener('contextmenu', (event) => {
|
||||
@ -170,6 +165,18 @@ class Messaging extends LitElement {
|
||||
})
|
||||
})
|
||||
parentEpml.imReady()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,38 +1,34 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { render } from 'lit/html.js'
|
||||
import { passiveSupport } from 'passive-events-support/src/utils'
|
||||
passiveSupport({
|
||||
events: ['touchstart']
|
||||
})
|
||||
import { Epml } from '../../../../epml.js';
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate';
|
||||
import { Epml } from '../../../../epml.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
import { qchatStyles } from './q-chat-css.src.js'
|
||||
import WebWorker from 'web-worker:./computePowWorker.src.js';
|
||||
import {repeat} from 'lit/directives/repeat.js';
|
||||
import { repeat } from 'lit/directives/repeat.js'
|
||||
import { Editor, Extension } from '@tiptap/core'
|
||||
import isElectron from 'is-electron'
|
||||
|
||||
registerTranslateConfig({
|
||||
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
|
||||
})
|
||||
|
||||
import '../../components/ChatWelcomePage.js'
|
||||
import '../../components/ChatHead.js'
|
||||
import '../../components/ChatPage.js'
|
||||
import '../../components/WrapperModal.js';
|
||||
import '../../components/ChatSeachResults.js';
|
||||
import snackbar from '../../components/snackbar.js'
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-snackbar'
|
||||
import '@vaadin/grid'
|
||||
import WebWorker from 'web-worker:./computePowWorker.src.js'
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import Underline from '@tiptap/extension-underline';
|
||||
import Placeholder from '@tiptap/extension-placeholder'
|
||||
import Highlight from '@tiptap/extension-highlight'
|
||||
import snackbar from '../../components/snackbar.js'
|
||||
|
||||
import '../../components/ChatWelcomePage.js'
|
||||
import '../../components/ChatHead.js'
|
||||
import '../../components/ChatPage.js'
|
||||
import '../../components/WrapperModal.js'
|
||||
import '../../components/ChatSearchResults.js'
|
||||
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-dialog'
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-snackbar'
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@vaadin/grid'
|
||||
|
||||
passiveSupport({ events: ['touchstart'] })
|
||||
|
||||
import { Editor, Extension } from '@tiptap/core'
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class Chat extends LitElement {
|
||||
@ -58,11 +54,11 @@ class Chat extends LitElement {
|
||||
userFoundModalOpen: { type: Boolean },
|
||||
userSelected: { type: Object },
|
||||
editor: {type: Object},
|
||||
groupInvites: { type: Array },
|
||||
groupInvites: { type: Array }
|
||||
}
|
||||
}
|
||||
|
||||
static styles = [qchatStyles]
|
||||
static styles = [qchatStyles]
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
@ -70,7 +66,6 @@ class Chat extends LitElement {
|
||||
this.config = {
|
||||
user: {
|
||||
node: {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,30 +95,28 @@ class Chat extends LitElement {
|
||||
this.groupInvites = []
|
||||
}
|
||||
|
||||
async setActiveChatHeadUrl(url) {
|
||||
async setActiveChatHeadUrl(url) {
|
||||
this.activeChatHeadUrl = ''
|
||||
await this.updateComplete;
|
||||
this.activeChatHeadUrl = url
|
||||
}
|
||||
|
||||
resetChatEditor(){
|
||||
|
||||
this.editor.commands.setContent('')
|
||||
|
||||
this.editor.commands.setContent('')
|
||||
}
|
||||
|
||||
async getUpdateCompleteTextEditor() {
|
||||
await super.getUpdateComplete();
|
||||
const marginElements = Array.from(this.shadowRoot.querySelectorAll('chat-text-editor'));
|
||||
await Promise.all(marginElements.map(el => el.updateComplete));
|
||||
const marginElements2 = Array.from(this.shadowRoot.querySelectorAll('wrapper-modal'));
|
||||
await Promise.all(marginElements2.map(el => el.updateComplete));
|
||||
return true;
|
||||
await super.getUpdateComplete()
|
||||
const marginElements = Array.from(this.shadowRoot.querySelectorAll('chat-text-editor'))
|
||||
await Promise.all(marginElements.map(el => el.updateComplete))
|
||||
const marginElements2 = Array.from(this.shadowRoot.querySelectorAll('wrapper-modal'))
|
||||
await Promise.all(marginElements2.map(el => el.updateComplete))
|
||||
return true
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
|
||||
super.connectedCallback();
|
||||
await this.getUpdateCompleteTextEditor();
|
||||
super.connectedCallback()
|
||||
await this.getUpdateCompleteTextEditor()
|
||||
|
||||
const elementChatId = this.shadowRoot.getElementById('messageBox').shadowRoot.getElementById('privateMessage')
|
||||
this.editor = new Editor({
|
||||
@ -152,43 +145,38 @@ class Chat extends LitElement {
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
this.unsubscribeStore = window.parent.reduxStore.subscribe(() => {
|
||||
try {
|
||||
|
||||
if(window.parent.location && window.parent.location.search){
|
||||
const queryString = window.parent.location.search;
|
||||
const params = new URLSearchParams(queryString);
|
||||
if(window.parent.location && window.parent.location.search) {
|
||||
const queryString = window.parent.location.search
|
||||
const params = new URLSearchParams(queryString)
|
||||
const chat = params.get("chat")
|
||||
if(chat && chat !== this.activeChatHeadUrl){
|
||||
let url = window.parent.location.href;
|
||||
let newUrl = url.split("?")[0];
|
||||
window.parent.history.pushState({}, "", newUrl);
|
||||
let url = window.parent.location.href
|
||||
let newUrl = url.split("?")[0]
|
||||
window.parent.history.pushState({}, "", newUrl)
|
||||
this.setActiveChatHeadUrl(chat)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.editor.destroy();
|
||||
this.unsubscribeStore();
|
||||
}
|
||||
super.disconnectedCallback()
|
||||
this.editor.destroy()
|
||||
this.unsubscribeStore()
|
||||
}
|
||||
|
||||
|
||||
updatePlaceholder(editor, text){
|
||||
updatePlaceholder(editor, text) {
|
||||
editor.extensionManager.extensions.forEach((extension) => {
|
||||
if (extension.name === "placeholder") {
|
||||
|
||||
extension.options["placeholder"] = text
|
||||
editor.commands.focus('end')
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -196,9 +184,8 @@ class Chat extends LitElement {
|
||||
<div class="container clearfix">
|
||||
<div class="people-list" id="people-list">
|
||||
<div class="search">
|
||||
<div class="create-chat" @click=${() => {
|
||||
this.openPrivateMessage = true;
|
||||
}}>${translate("chatpage.cchange1")}
|
||||
<div class="create-chat" @click=${() => { this.openPrivateMessage = true }}>
|
||||
${translate("chatpage.cchange1")}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="list">
|
||||
@ -207,9 +194,7 @@ class Chat extends LitElement {
|
||||
<div class="blockedusers">
|
||||
<!-- <div class="groups-button-container">
|
||||
<button
|
||||
@click=${() => {
|
||||
this.redirectToGroups();
|
||||
}}
|
||||
@click=${() => { this.redirectToGroups() }}
|
||||
class="groups-button">
|
||||
<mwc-icon>groups</mwc-icon>
|
||||
${translate("sidemenu.groupmanagement")}
|
||||
@ -246,11 +231,11 @@ class Chat extends LitElement {
|
||||
<!-- Start Chatting Dialog -->
|
||||
<wrapper-modal
|
||||
.onClickFunc=${() => {
|
||||
this.resetChatEditor();
|
||||
this.openPrivateMessage = false;
|
||||
this.shadowRoot.getElementById('sendTo').value = "";
|
||||
this.resetChatEditor()
|
||||
this.openPrivateMessage = false
|
||||
this.shadowRoot.getElementById('sendTo').value = ""
|
||||
this.userFoundModalOpen = false;
|
||||
this.userFound = [];
|
||||
this.userFound = []
|
||||
} }
|
||||
style=${this.openPrivateMessage ? "visibility:visible;z-index:50" : "visibility: hidden;z-index:-100;position: relative"}>
|
||||
<div style=${"position: relative"}>
|
||||
@ -269,9 +254,9 @@ class Chat extends LitElement {
|
||||
placeholder="${translate("chatpage.cchange7")}"
|
||||
value=${this.userSelected.name ? this.userSelected.name: ''}
|
||||
@keypress=${() => {
|
||||
this.userSelected = {};
|
||||
this.requestUpdate();
|
||||
}}
|
||||
this.userSelected = {}
|
||||
this.requestUpdate()
|
||||
}}
|
||||
/>
|
||||
${this.userSelected.name ? (
|
||||
html`
|
||||
@ -321,10 +306,8 @@ class Chat extends LitElement {
|
||||
class="modal-button"
|
||||
@click=${()=> {
|
||||
const chatTextEditor = this.shadowRoot.getElementById('messageBox')
|
||||
chatTextEditor.sendMessageFunc({
|
||||
})
|
||||
|
||||
|
||||
chatTextEditor.sendMessageFunc({
|
||||
})
|
||||
}}
|
||||
?disabled="${this.isLoading}">
|
||||
${this.isLoading === false
|
||||
@ -364,9 +347,9 @@ class Chat extends LitElement {
|
||||
<vaadin-grid theme="compact" id="blockedGrid" ?hidden="${this.isEmptyArray(this.blockedUserList)}" aria-label="Blocked List" .items="${this.blockedUserList}" all-rows-visible>
|
||||
<vaadin-grid-column auto-width header="${translate("chatpage.cchange11")}" .renderer=${(root, column, data) => {
|
||||
if (data.item.name === "No registered name") {
|
||||
render(html`${translate("chatpage.cchange15")}`, root);
|
||||
render(html`${translate("chatpage.cchange15")}`, root)
|
||||
} else {
|
||||
render(html`${data.item.name}`, root);
|
||||
render(html`${data.item.name}`, root)
|
||||
}
|
||||
}}>
|
||||
</vaadin-grid-column>
|
||||
@ -392,14 +375,11 @@ class Chat extends LitElement {
|
||||
`
|
||||
}
|
||||
|
||||
|
||||
|
||||
async firstUpdated() {
|
||||
this.changeLanguage();
|
||||
this.changeTheme();
|
||||
this.getChatBlockedList();
|
||||
this.getLocalBlockedList();
|
||||
// await this.getPendingGroupInvites();
|
||||
async firstUpdated() {
|
||||
this.changeTheme()
|
||||
this.getChatBlockedList()
|
||||
this.getLocalBlockedList()
|
||||
// await this.getPendingGroupInvites()
|
||||
|
||||
const getBlockedUsers = async () => {
|
||||
let blockedUsers = await parentEpml.request('apiCall', {
|
||||
@ -410,15 +390,15 @@ class Chat extends LitElement {
|
||||
}
|
||||
|
||||
const stopKeyEventPropagation = (e) => {
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
e.stopPropagation()
|
||||
return false
|
||||
}
|
||||
|
||||
const nameInput = this.shadowRoot.getElementById('sendTo');
|
||||
const nameInput = this.shadowRoot.getElementById('sendTo')
|
||||
|
||||
nameInput.addEventListener('keydown', stopKeyEventPropagation);
|
||||
nameInput.addEventListener('keydown', stopKeyEventPropagation)
|
||||
|
||||
this.shadowRoot.getElementById('messageBox').addEventListener('keydown', stopKeyEventPropagation);
|
||||
this.shadowRoot.getElementById('messageBox').addEventListener('keydown', stopKeyEventPropagation)
|
||||
|
||||
const runFunctionsAfterPageLoad = () => {
|
||||
// Functions to exec after render while waiting for page info...
|
||||
@ -440,14 +420,11 @@ class Chat extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
let runFunctionsAfterPageLoadInterval = setInterval(runFunctionsAfterPageLoad, 100);
|
||||
let runFunctionsAfterPageLoadInterval = setInterval(runFunctionsAfterPageLoad, 100)
|
||||
|
||||
window.addEventListener('storage', () => {
|
||||
const checkLanguage = localStorage.getItem('qortalLanguage')
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
|
||||
use(checkLanguage)
|
||||
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark'
|
||||
} else {
|
||||
@ -491,7 +468,18 @@ class Chat extends LitElement {
|
||||
})
|
||||
})
|
||||
parentEpml.imReady()
|
||||
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
setOpenPrivateMessage(props) {
|
||||
@ -500,10 +488,10 @@ class Chat extends LitElement {
|
||||
}
|
||||
|
||||
async userSearch() {
|
||||
const nameValue = this.shadowRoot.getElementById('sendTo').value;
|
||||
const nameValue = this.shadowRoot.getElementById('sendTo').value
|
||||
if(!nameValue) {
|
||||
this.userFound = [];
|
||||
this.userFoundModalOpen = true;
|
||||
this.userFound = []
|
||||
this.userFoundModalOpen = true
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@ -512,7 +500,7 @@ class Chat extends LitElement {
|
||||
url: `/names/${nameValue}`
|
||||
})
|
||||
if (result.error === 401) {
|
||||
this.userFound = [];
|
||||
this.userFound = []
|
||||
} else {
|
||||
this.userFound = [
|
||||
...this.userFound,
|
||||
@ -535,7 +523,7 @@ class Chat extends LitElement {
|
||||
|
||||
const trimmedMessage = msg
|
||||
if (/^\s*$/.test(trimmedMessage)) {
|
||||
this.isLoading = false;
|
||||
this.isLoading = false
|
||||
} else {
|
||||
const messageObject = {
|
||||
messageText: trimmedMessage,
|
||||
@ -544,19 +532,19 @@ class Chat extends LitElement {
|
||||
version: 3
|
||||
}
|
||||
const stringifyMessageObject = JSON.stringify(messageObject)
|
||||
this.sendMessage(stringifyMessageObject);
|
||||
this.sendMessage(stringifyMessageObject)
|
||||
}
|
||||
}
|
||||
|
||||
async sendMessage(messageText) {
|
||||
this.isLoading = true;
|
||||
this.isLoading = true
|
||||
|
||||
const _recipient = this.shadowRoot.getElementById('sendTo').value;
|
||||
const _recipient = this.shadowRoot.getElementById('sendTo').value
|
||||
|
||||
let recipient;
|
||||
let recipient
|
||||
|
||||
const validateName = async (receiverName) => {
|
||||
let myRes;
|
||||
let myRes
|
||||
try {
|
||||
let myNameRes = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
@ -565,19 +553,19 @@ class Chat extends LitElement {
|
||||
if (myNameRes.error === 401) {
|
||||
myRes = false;
|
||||
} else {
|
||||
myRes = myNameRes;
|
||||
myRes = myNameRes
|
||||
}
|
||||
return myRes;
|
||||
} catch (error) {
|
||||
return "";
|
||||
return ""
|
||||
}
|
||||
};
|
||||
|
||||
const myNameRes = await validateName(_recipient);
|
||||
const myNameRes = await validateName(_recipient)
|
||||
if (!myNameRes) {
|
||||
recipient = _recipient;
|
||||
recipient = _recipient
|
||||
} else {
|
||||
recipient = myNameRes.owner;
|
||||
recipient = myNameRes.owner
|
||||
};
|
||||
|
||||
const getAddressPublicKey = async () => {
|
||||
@ -590,23 +578,23 @@ class Chat extends LitElement {
|
||||
})
|
||||
|
||||
if (addressPublicKey.error === 102) {
|
||||
_publicKey = false;
|
||||
let err4string = get("chatpage.cchange19");
|
||||
parentEpml.request('showSnackBar', `${err4string}`);
|
||||
this.isLoading = false;
|
||||
_publicKey = false
|
||||
let err4string = get("chatpage.cchange19")
|
||||
parentEpml.request('showSnackBar', `${err4string}`)
|
||||
this.isLoading = false
|
||||
} else if (addressPublicKey !== false) {
|
||||
isEncrypted = 1;
|
||||
_publicKey = addressPublicKey;
|
||||
sendMessageRequest(isEncrypted, _publicKey);
|
||||
isEncrypted = 1
|
||||
_publicKey = addressPublicKey
|
||||
sendMessageRequest(isEncrypted, _publicKey)
|
||||
} else {
|
||||
let err4string = get("chatpage.cchange39");
|
||||
parentEpml.request('showSnackBar', `${err4string}`);
|
||||
this.isLoading = false;
|
||||
let err4string = get("chatpage.cchange39")
|
||||
parentEpml.request('showSnackBar', `${err4string}`)
|
||||
this.isLoading = false
|
||||
}
|
||||
};
|
||||
let _reference = new Uint8Array(64);
|
||||
let _reference = new Uint8Array(64)
|
||||
window.crypto.getRandomValues(_reference);
|
||||
let reference = window.parent.Base58.encode(_reference);
|
||||
let reference = window.parent.Base58.encode(_reference)
|
||||
const sendMessageRequest = async (isEncrypted, _publicKey) => {
|
||||
let chatResponse = await parentEpml.request('chat', {
|
||||
type: 18,
|
||||
@ -622,26 +610,26 @@ class Chat extends LitElement {
|
||||
isEncrypted: 1,
|
||||
isText: 1
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
_computePow(chatResponse);
|
||||
};
|
||||
|
||||
const _computePow = async (chatBytes) => {
|
||||
const difficulty = this.balance < 4 ? 18 : 8
|
||||
const path = window.parent.location.origin + '/memory-pow/memory-pow.wasm.full';
|
||||
const worker = new WebWorker();
|
||||
let nonce = null;
|
||||
const path = window.parent.location.origin + '/memory-pow/memory-pow.wasm.full'
|
||||
const worker = new WebWorker()
|
||||
let nonce = null
|
||||
let chatBytesArray = null;
|
||||
await new Promise((res, rej) => {
|
||||
worker.postMessage({chatBytes, path, difficulty});
|
||||
worker.postMessage({chatBytes, path, difficulty})
|
||||
worker.onmessage = e => {
|
||||
worker.terminate();
|
||||
chatBytesArray = e.data.chatBytesArray;
|
||||
nonce = e.data.nonce;
|
||||
res();
|
||||
worker.terminate()
|
||||
chatBytesArray = e.data.chatBytesArray
|
||||
nonce = e.data.nonce
|
||||
res()
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
let _response = await parentEpml.request('sign_chat', {
|
||||
nonce: this.selectedAddress.nonce,
|
||||
@ -649,36 +637,36 @@ class Chat extends LitElement {
|
||||
chatNonce: nonce
|
||||
});
|
||||
|
||||
getSendChatResponse(_response);
|
||||
getSendChatResponse(_response)
|
||||
};
|
||||
|
||||
const getSendChatResponse = (response) => {
|
||||
if (response === true) {
|
||||
this.setActiveChatHeadUrl(`direct/${recipient}`);
|
||||
this.shadowRoot.getElementById('sendTo').value = "";
|
||||
this.openPrivateMessage = false;
|
||||
this.setActiveChatHeadUrl(`direct/${recipient}`)
|
||||
this.shadowRoot.getElementById('sendTo').value = ""
|
||||
this.openPrivateMessage = false
|
||||
this.resetChatEditor();
|
||||
} else if (response.error) {
|
||||
parentEpml.request('showSnackBar', response.message);
|
||||
parentEpml.request('showSnackBar', response.message)
|
||||
} else {
|
||||
let err2string = get("chatpage.cchange21");
|
||||
parentEpml.request('showSnackBar', `${err2string}`);
|
||||
let err2string = get("chatpage.cchange21")
|
||||
parentEpml.request('showSnackBar', `${err2string}`)
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
};
|
||||
this.isLoading = false
|
||||
}
|
||||
|
||||
// Exec..
|
||||
getAddressPublicKey();
|
||||
getAddressPublicKey()
|
||||
|
||||
}
|
||||
|
||||
insertImage(file) {
|
||||
if (file.type.includes('image')) {
|
||||
this.imageFile = file;
|
||||
return;
|
||||
this.imageFile = file
|
||||
return
|
||||
}
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange28"));
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange28"))
|
||||
}
|
||||
|
||||
renderLoadingText() {
|
||||
@ -724,7 +712,7 @@ class Chat extends LitElement {
|
||||
|
||||
localStorage.removeItem("ChatBlockedAddresses")
|
||||
|
||||
var obj = [];
|
||||
var obj = []
|
||||
|
||||
fetch(blockedAddressesUrl).then(response => {
|
||||
return response.json()
|
||||
@ -751,7 +739,7 @@ class Chat extends LitElement {
|
||||
})
|
||||
}
|
||||
|
||||
async getPendingGroupInvites() {
|
||||
async getPendingGroupInvites() {
|
||||
const myAddress = window.parent.reduxStore.getState().app.selectedAddress.address
|
||||
try {
|
||||
let pendingGroupInvites = await parentEpml.request('apiCall', {
|
||||
@ -810,91 +798,86 @@ class Chat extends LitElement {
|
||||
changeTheme() {
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark';
|
||||
this.theme = 'dark'
|
||||
} else {
|
||||
this.theme = 'light';
|
||||
}
|
||||
document.querySelector('html').setAttribute('theme', this.theme);
|
||||
}
|
||||
|
||||
changeLanguage() {
|
||||
const checkLanguage = localStorage.getItem('qortalLanguage')
|
||||
|
||||
if (checkLanguage === null || checkLanguage.length === 0) {
|
||||
localStorage.setItem('qortalLanguage', 'us')
|
||||
use('us')
|
||||
} else {
|
||||
use(checkLanguage)
|
||||
this.theme = 'light'
|
||||
}
|
||||
document.querySelector('html').setAttribute('theme', this.theme)
|
||||
}
|
||||
|
||||
renderChatWelcomePage() {
|
||||
return html`
|
||||
<chat-welcome-page
|
||||
myAddress=${JSON.stringify(this.selectedAddress)}
|
||||
.setOpenPrivateMessage=${(val) => this.setOpenPrivateMessage(val)}>
|
||||
.setOpenPrivateMessage=${(val) => this.setOpenPrivateMessage(val)}
|
||||
>
|
||||
</chat-welcome-page>`
|
||||
}
|
||||
|
||||
renderChatHead(chatHeadArr) {
|
||||
|
||||
return chatHeadArr.map(eachChatHead => {
|
||||
return html`<chat-head activeChatHeadUrl=${this.activeChatHeadUrl} .setActiveChatHeadUrl=${(val)=> this.setActiveChatHeadUrl(val)} chatInfo=${JSON.stringify(eachChatHead)}></chat-head>`
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
renderChatPage() {
|
||||
|
||||
// Check for the chat ID from and render chat messages
|
||||
// Else render Welcome to Q-CHat
|
||||
|
||||
// TODO: DONE: Do the above in the ChatPage
|
||||
return html`
|
||||
<chat-page
|
||||
.chatHeads=${this.chatHeads}
|
||||
.hideNewMessageBar=${this.hideNewMessageBar}
|
||||
.showNewMessageBar=${this.showNewMessageBar}
|
||||
myAddress=${window.parent.reduxStore.getState().app.selectedAddress.address}
|
||||
chatId=${this.activeChatHeadUrl}
|
||||
.setOpenPrivateMessage=${(val) => this.setOpenPrivateMessage(val)}
|
||||
.setActiveChatHeadUrl=${(val)=> this.setActiveChatHeadUrl(val)}>
|
||||
</chat-page>
|
||||
<chat-page
|
||||
.chatHeads=${this.chatHeads}
|
||||
.hideNewMessageBar=${this.hideNewMessageBar}
|
||||
.showNewMessageBar=${this.showNewMessageBar}
|
||||
myAddress=${window.parent.reduxStore.getState().app.selectedAddress.address}
|
||||
chatId=${this.activeChatHeadUrl}
|
||||
.setOpenPrivateMessage=${(val) => this.setOpenPrivateMessage(val)}
|
||||
.setActiveChatHeadUrl=${(val)=> this.setActiveChatHeadUrl(val)}
|
||||
>
|
||||
</chat-page>
|
||||
`
|
||||
}
|
||||
|
||||
setChatHeads(chatObj) {
|
||||
const chatObjGroups = Array.isArray(chatObj.groups) ? chatObj.groups : [];
|
||||
const chatObjDirect = Array.isArray(chatObj.direct) ? chatObj.direct : [];
|
||||
let groupList = chatObjGroups.map(group => group.groupId === 0 ? { groupId: group.groupId, url: `group/${group.groupId}`, groupName: "Qortal General Chat", timestamp: group.timestamp === undefined ? 2 : group.timestamp, sender: group.sender } : { ...group, timestamp: group.timestamp === undefined ? 1 : group.timestamp, url: `group/${group.groupId}` })
|
||||
const chatObjGroups = Array.isArray(chatObj.groups) ? chatObj.groups : []
|
||||
const chatObjDirect = Array.isArray(chatObj.direct) ? chatObj.direct : []
|
||||
|
||||
let groupList = chatObjGroups.map(group => group.groupId === 0 ? {
|
||||
groupId: group.groupId, url: `group/${group.groupId}`,
|
||||
groupName: "Qortal General Chat",
|
||||
timestamp: group.timestamp === undefined ? 2 : group.timestamp,
|
||||
sender: group.sender } : { ...group, timestamp: group.timestamp === undefined ? 1 : group.timestamp, url: `group/${group.groupId}`
|
||||
})
|
||||
|
||||
let directList = chatObjDirect.map(dc => {
|
||||
return { ...dc, url: `direct/${dc.address}` }
|
||||
})
|
||||
|
||||
const compareNames = (a, b) => {
|
||||
return a.groupName.localeCompare(b.groupName)
|
||||
}
|
||||
|
||||
groupList.sort(compareNames)
|
||||
let chatHeadMasterList = [...groupList, ...directList]
|
||||
|
||||
const compareArgs = (a, b) => {
|
||||
return b.timestamp - a.timestamp
|
||||
}
|
||||
|
||||
this.chatHeads = chatHeadMasterList.sort(compareArgs)
|
||||
}
|
||||
|
||||
getChatHeadFromState(chatObj) {
|
||||
|
||||
if (chatObj === undefined) {
|
||||
return
|
||||
} else {
|
||||
|
||||
this.chatHeadsObj = chatObj
|
||||
this.setChatHeads(chatObj)
|
||||
}
|
||||
}
|
||||
|
||||
_textArea(e) {
|
||||
|
||||
if (e.keyCode === 13 && !e.shiftKey) this._sendMessage()
|
||||
}
|
||||
|
||||
@ -908,13 +891,13 @@ class Chat extends LitElement {
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
let apiKey = myNode.apiKey
|
||||
return apiKey
|
||||
}
|
||||
|
||||
scrollToBottom() {
|
||||
const viewElement = this.shadowRoot.querySelector('chat-page').shadowRoot.querySelector('chat-scroller').shadowRoot.getElementById('viewElement');
|
||||
const viewElement = this.shadowRoot.querySelector('chat-page').shadowRoot.querySelector('chat-scroller').shadowRoot.getElementById('viewElement')
|
||||
viewElement.scroll({ top: viewElement.scrollHeight, left: 0, behavior: 'smooth' })
|
||||
}
|
||||
|
||||
|
@ -347,7 +347,6 @@ class MintingInfo extends LitElement {
|
||||
}
|
||||
|
||||
async firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
|
||||
@ -429,6 +428,18 @@ class MintingInfo extends LitElement {
|
||||
})
|
||||
})
|
||||
parentEpml.imReady()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
async getAddressLevel() {
|
||||
|
@ -537,7 +537,6 @@ class NameRegistration extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
this.unitFee()
|
||||
@ -604,6 +603,18 @@ class NameRegistration extends LitElement {
|
||||
})
|
||||
})
|
||||
parentEpml.imReady()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
|
@ -609,6 +609,18 @@ class NamesMarket extends LitElement {
|
||||
})
|
||||
})
|
||||
parentEpml.imReady()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
displayTabContent(tab) {
|
||||
|
@ -34,10 +34,8 @@ class NodeManagement extends LitElement {
|
||||
confPeerMessage: { type: String },
|
||||
addMintingAccountMessage: { type: String },
|
||||
removeMintingAccountMessage: { type: String },
|
||||
tempMintingAccount: { type: Object },
|
||||
nodeConfig: { type: Object },
|
||||
nodeDomain: { type: String },
|
||||
myElementId: { type: String },
|
||||
theme: { type: String, reflect: true }
|
||||
}
|
||||
}
|
||||
@ -138,15 +136,13 @@ class NodeManagement extends LitElement {
|
||||
this.addPeerMessage = ""
|
||||
this.confPeerMessage = ""
|
||||
this.addMintingAccountMessage = ""
|
||||
this.tempMintingAccount = {}
|
||||
this.config = {
|
||||
user: {
|
||||
node: {},
|
||||
},
|
||||
};
|
||||
}
|
||||
this.nodeConfig = {}
|
||||
this.nodeDomain = ""
|
||||
this.myElementId = ''
|
||||
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
|
||||
}
|
||||
|
||||
@ -278,11 +274,10 @@ class NodeManagement extends LitElement {
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
this.updateMintingAccounts()
|
||||
@ -311,86 +306,84 @@ class NodeManagement extends LitElement {
|
||||
|
||||
// Calculate HH MM SS from Milliseconds...
|
||||
const convertMsToTime = (milliseconds) => {
|
||||
let day, hour, minute, seconds;
|
||||
seconds = Math.floor(milliseconds / 1000);
|
||||
minute = Math.floor(seconds / 60);
|
||||
seconds = seconds % 60;
|
||||
hour = Math.floor(minute / 60);
|
||||
minute = minute % 60;
|
||||
day = Math.floor(hour / 24);
|
||||
hour = hour % 24;
|
||||
let day, hour, minute, seconds
|
||||
seconds = Math.floor(milliseconds / 1000)
|
||||
minute = Math.floor(seconds / 60)
|
||||
seconds = seconds % 60
|
||||
hour = Math.floor(minute / 60)
|
||||
minute = minute % 60
|
||||
day = Math.floor(hour / 24)
|
||||
hour = hour % 24
|
||||
if (isNaN(day)) {
|
||||
return "offline";
|
||||
return "offline"
|
||||
}
|
||||
return day + "d " + hour + "h " + minute + "m";
|
||||
};
|
||||
return day + "d " + hour + "h " + minute + "m"
|
||||
}
|
||||
|
||||
const getNodeUpTime = () => {
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/admin/uptime`,
|
||||
})
|
||||
.then((res) => {
|
||||
this.upTime = "";
|
||||
setTimeout(() => {
|
||||
this.upTime = convertMsToTime(res);
|
||||
}, 1);
|
||||
});
|
||||
|
||||
setTimeout(getNodeUpTime, this.config.user.nodeSettings.pingInterval);
|
||||
};
|
||||
this.upTime = ""
|
||||
parentEpml.request("apiCall", { url: `/admin/uptime` }).then((res) => {
|
||||
this.upTime = convertMsToTime(res)
|
||||
})
|
||||
setTimeout(getNodeUpTime, 60000)
|
||||
}
|
||||
|
||||
const updatePeers = () => {
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
url: `/peers`,
|
||||
})
|
||||
.then((res) => {
|
||||
setTimeout(() => {
|
||||
this.peers = res;
|
||||
}, 1);
|
||||
});
|
||||
setTimeout(updatePeers, this.config.user.nodeSettings.pingInterval);
|
||||
};
|
||||
this.peers = []
|
||||
parentEpml.request("apiCall", { url: `/peers` }).then((res) => {
|
||||
this.peers = res
|
||||
})
|
||||
setTimeout(updatePeers, 60000)
|
||||
}
|
||||
|
||||
const getNodeConfig = () => {
|
||||
this.nodeConfig = {}
|
||||
this.nodeDomain = ""
|
||||
parentEpml.request("getNodeConfig").then((res) => {
|
||||
setTimeout(() => {
|
||||
this.nodeConfig = res;
|
||||
}, 1);
|
||||
let myNode = window.parent.reduxStore.getState().app.nodeConfig
|
||||
.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
this.nodeDomain = myNode.domain + ":" + myNode.port;
|
||||
});
|
||||
|
||||
setTimeout(getNodeConfig, 1000);
|
||||
};
|
||||
this.nodeConfig = res
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
this.nodeDomain = myNode.domain + ":" + myNode.port
|
||||
})
|
||||
setTimeout(getNodeConfig, 60000)
|
||||
}
|
||||
|
||||
let configLoaded = false
|
||||
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe("config", async c => {
|
||||
if (!configLoaded) {
|
||||
setTimeout(getNodeUpTime, 1);
|
||||
setTimeout(updatePeers, 1);
|
||||
setTimeout(this.updateMintingAccounts, 1);
|
||||
setTimeout(getNodeConfig, 1);
|
||||
configLoaded = true;
|
||||
setTimeout(getNodeUpTime, 1)
|
||||
setTimeout(updatePeers, 1)
|
||||
setTimeout(this.updateMintingAccounts, 1)
|
||||
setTimeout(getNodeConfig, 1)
|
||||
configLoaded = true
|
||||
}
|
||||
this.config = JSON.parse(c);
|
||||
this.config = JSON.parse(c)
|
||||
})
|
||||
})
|
||||
parentEpml.imReady()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark';
|
||||
this.theme = 'dark'
|
||||
} else {
|
||||
this.theme = 'light';
|
||||
this.theme = 'light'
|
||||
}
|
||||
document.querySelector('html').setAttribute('theme', this.theme);
|
||||
document.querySelector('html').setAttribute('theme', this.theme)
|
||||
}
|
||||
|
||||
changeLanguage() {
|
||||
@ -421,8 +414,8 @@ class NodeManagement extends LitElement {
|
||||
})
|
||||
.then((res) => {
|
||||
let err3string = get("nodepage.nchange25")
|
||||
parentEpml.request('showSnackBar', `${err3string}` + peerAddress);
|
||||
});
|
||||
parentEpml.request('showSnackBar', `${err3string}` + peerAddress)
|
||||
})
|
||||
}
|
||||
|
||||
removePeer(peerAddress, rowIndex) {
|
||||
@ -434,9 +427,9 @@ class NodeManagement extends LitElement {
|
||||
})
|
||||
.then((res) => {
|
||||
let err4string = get("nodepage.nchange26")
|
||||
parentEpml.request('showSnackBar', `${err4string}` + peerAddress);
|
||||
this.peers.splice(rowIndex, 1);
|
||||
});
|
||||
parentEpml.request('showSnackBar', `${err4string}` + peerAddress)
|
||||
this.peers.splice(rowIndex, 1)
|
||||
})
|
||||
}
|
||||
|
||||
stopNode() {
|
||||
@ -446,9 +439,9 @@ class NodeManagement extends LitElement {
|
||||
method: "GET"
|
||||
})
|
||||
.then((res) => {
|
||||
let err7string = get("nodepage.nchange32")
|
||||
parentEpml.request('showSnackBar', `${err7string}`);
|
||||
});
|
||||
let err7string = get("nodepage.nchange32")
|
||||
parentEpml.request('showSnackBar', `${err7string}`)
|
||||
})
|
||||
}
|
||||
|
||||
restartNode() {
|
||||
@ -458,19 +451,18 @@ class NodeManagement extends LitElement {
|
||||
method: "GET"
|
||||
})
|
||||
.then((res) => {
|
||||
let err7string = get("nodepage.nchange34")
|
||||
parentEpml.request('showSnackBar', `${err7string}`);
|
||||
});
|
||||
let err7string = get("nodepage.nchange34")
|
||||
parentEpml.request('showSnackBar', `${err7string}`)
|
||||
})
|
||||
}
|
||||
|
||||
onPageNavigation(pageUrl) {
|
||||
parentEpml.request("setPageUrl", pageUrl);
|
||||
parentEpml.request("setPageUrl", pageUrl)
|
||||
}
|
||||
|
||||
addPeer(e) {
|
||||
this.addPeerLoading = true;
|
||||
const addPeerAddress = this.shadowRoot.querySelector("#addPeerAddress")
|
||||
.value;
|
||||
this.addPeerLoading = true
|
||||
const addPeerAddress = this.shadowRoot.querySelector("#addPeerAddress").value
|
||||
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
@ -479,18 +471,16 @@ class NodeManagement extends LitElement {
|
||||
body: addPeerAddress,
|
||||
})
|
||||
.then((res) => {
|
||||
this.addPeerMessage = res.message;
|
||||
this.addPeerLoading = false;
|
||||
});
|
||||
this.addPeerMessage = res.message
|
||||
this.addPeerLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
addMintingAccount(e) {
|
||||
this.addMintingAccountLoading = true;
|
||||
this.addMintingAccountMessage = "Loading...";
|
||||
this.addMintingAccountLoading = true
|
||||
this.addMintingAccountMessage = "Loading..."
|
||||
|
||||
this.addMintingAccountKey = this.shadowRoot.querySelector(
|
||||
"#addMintingAccountKey"
|
||||
).value;
|
||||
this.addMintingAccountKey = this.shadowRoot.querySelector("#addMintingAccountKey").value
|
||||
|
||||
parentEpml
|
||||
.request("apiCall", {
|
||||
@ -500,28 +490,28 @@ class NodeManagement extends LitElement {
|
||||
})
|
||||
.then((res) => {
|
||||
if (res === true) {
|
||||
this.updateMintingAccounts();
|
||||
this.addMintingAccountKey = "";
|
||||
this.addMintingAccountMessage = this.renderErr1Text();
|
||||
this.addMintingAccountLoading = false;
|
||||
this.updateMintingAccounts()
|
||||
this.addMintingAccountKey = ""
|
||||
this.addMintingAccountMessage = this.renderErr1Text()
|
||||
this.addMintingAccountLoading = false
|
||||
} else {
|
||||
this.addMintingAccountKey = "";
|
||||
this.addMintingAccountMessage = this.renderErr2Text(); // Corrected an error here thanks to crow (-_-)
|
||||
this.addMintingAccountLoading = false;
|
||||
this.addMintingAccountKey = ""
|
||||
this.addMintingAccountMessage = this.renderErr2Text() // Corrected an error here thanks to crow (-_-)
|
||||
this.addMintingAccountLoading = false
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
updateMintingAccounts() {
|
||||
parentEpml.request("apiCall", {
|
||||
url: `/admin/mintingaccounts`,
|
||||
}).then((res) => {
|
||||
setTimeout(() => this.mintingAccounts = res, 1);
|
||||
});
|
||||
this.mintingAccounts = []
|
||||
parentEpml.request("apiCall", { url: `/admin/mintingaccounts` }).then((res) => {
|
||||
this.mintingAccounts = res
|
||||
})
|
||||
console.clear()
|
||||
}
|
||||
|
||||
removeMintingAccount(publicKey) {
|
||||
this.removeMintingAccountLoading = true;
|
||||
this.removeMintingAccountLoading = true
|
||||
|
||||
parentEpml.request("apiCall", {
|
||||
url: `/admin/mintingaccounts?apiKey=${this.getApiKey()}`,
|
||||
@ -529,28 +519,28 @@ class NodeManagement extends LitElement {
|
||||
body: publicKey,
|
||||
}).then((res) => {
|
||||
if (res === true) {
|
||||
this.updateMintingAccounts();
|
||||
this.removeMintingAccountLoading = false;
|
||||
this.updateMintingAccounts()
|
||||
this.removeMintingAccountLoading = false
|
||||
let err5string = get("nodepage.nchange29")
|
||||
parentEpml.request('showSnackBar', `${err5string}`);
|
||||
parentEpml.request('showSnackBar', `${err5string}`)
|
||||
} else {
|
||||
this.removeMintingAccountLoading = false;
|
||||
this.removeMintingAccountLoading = false
|
||||
let err6string = get("nodepage.nchange30")
|
||||
parentEpml.request('showSnackBar', `${err6string}`);
|
||||
parentEpml.request('showSnackBar', `${err6string}`)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
let apiKey = myNode.apiKey
|
||||
return apiKey
|
||||
}
|
||||
|
||||
isEmptyArray(arr) {
|
||||
if (!arr) return true;
|
||||
return arr.length === 0;
|
||||
if (!arr) return true
|
||||
return arr.length === 0
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define("node-management", NodeManagement);
|
||||
window.customElements.define("node-management", NodeManagement)
|
||||
|
@ -79,6 +79,8 @@ a:not([href]):not([tabindex]):focus {
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border-style: none;
|
||||
height: 128px;
|
||||
width: 128px;
|
||||
}
|
||||
|
||||
caption {
|
||||
|
@ -1,22 +1,23 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { Epml } from '../../../epml.js'
|
||||
import { use, get, translate, registerTranslateConfig } from 'lit-translate'
|
||||
import isElectron from 'is-electron'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
import { overviewStyle } from './overview-page-css.js'
|
||||
import { asyncReplace } from 'lit/directives/async-replace.js'
|
||||
import isElectron from 'is-electron'
|
||||
|
||||
import "@material/mwc-button"
|
||||
import '@material/mwc-dialog'
|
||||
import '@vaadin/button';
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@vaadin/button'
|
||||
|
||||
registerTranslateConfig({
|
||||
loader: (lang) => fetch(`/language/${lang}.json`).then((res) => res.json()),
|
||||
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
|
||||
})
|
||||
|
||||
async function* countDown(count, callback) {
|
||||
while (count > 0) {
|
||||
yield count--;
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
yield count--
|
||||
await new Promise((r) => setTimeout(r, 1000))
|
||||
if (count === 0) {
|
||||
callback()
|
||||
}
|
||||
@ -34,7 +35,10 @@ class OverviewPage extends LitElement {
|
||||
nodeInfo: { type: Array },
|
||||
coreInfo: { type: Array },
|
||||
imageUrl: { type: String },
|
||||
myBalance: { type: Number }
|
||||
myBalance: { type: Number },
|
||||
listAccounts: { type: Array },
|
||||
check1: { type: Boolean },
|
||||
check2: { type: Boolean }
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +56,9 @@ class OverviewPage extends LitElement {
|
||||
this.coreInfo = []
|
||||
this.imageUrl = ''
|
||||
this.myBalance = 0
|
||||
this.listAccounts = []
|
||||
this.check1 = false
|
||||
this.check2 = false
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -114,7 +121,7 @@ class OverviewPage extends LitElement {
|
||||
</div>
|
||||
<div>
|
||||
<span class="heading"><span class="${this.cssStatus2}">${this.renderSyncStatus()}</span></span>
|
||||
<span class="description">${translate("walletpage.wchange41")}</span>
|
||||
<span class="description">${translate("walletprofile.wp5")}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -132,7 +139,7 @@ class OverviewPage extends LitElement {
|
||||
`
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
async firstUpdated() {
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
|
||||
@ -142,6 +149,7 @@ class OverviewPage extends LitElement {
|
||||
this.getNodeInfo()
|
||||
this.getCoreInfo()
|
||||
this.getBalanceInfo()
|
||||
await this.getMintingKeysList()
|
||||
|
||||
window.addEventListener('storage', () => {
|
||||
const checkLanguage = localStorage.getItem('qortalLanguage')
|
||||
@ -168,14 +176,31 @@ class OverviewPage extends LitElement {
|
||||
setInterval(() => {
|
||||
this.refreshItems()
|
||||
}, 60000)
|
||||
|
||||
setInterval(() => {
|
||||
this.getAvatar()
|
||||
}, 180000)
|
||||
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
const checkTheme = localStorage.getItem('qortalTheme')
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark';
|
||||
this.theme = 'dark'
|
||||
} else {
|
||||
this.theme = 'light';
|
||||
this.theme = 'light'
|
||||
}
|
||||
document.querySelector('html').setAttribute('theme', this.theme)
|
||||
}
|
||||
@ -191,22 +216,87 @@ class OverviewPage extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
refreshItems() {
|
||||
renderMyErrorMsg1() {
|
||||
return html`${translate("startminting.smchange1")}`
|
||||
}
|
||||
|
||||
async refreshItems() {
|
||||
this.nodeConfig = window.parent.reduxStore.getState().app.nodeConfig
|
||||
this.accountInfo = window.parent.reduxStore.getState().app.accountInfo
|
||||
this.getNodeInfo()
|
||||
this.getCoreInfo()
|
||||
this.getBalanceInfo()
|
||||
await this.getMintingKeysList()
|
||||
}
|
||||
|
||||
async getMintingKeysList() {
|
||||
this.check1 = false
|
||||
this.check2 = false
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeStatus = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
const statusUrl = `${nodeStatus}/admin/mintingaccounts`
|
||||
|
||||
try {
|
||||
const res = await fetch(statusUrl)
|
||||
const listAccounts = await res.json()
|
||||
this.listAccounts = listAccounts
|
||||
|
||||
const addressInfo = window.parent.reduxStore.getState().app.accountInfo.addressInfo
|
||||
const address = window.parent.reduxStore.getState().app.selectedAddress.address
|
||||
const findMyMintingAccount = this.listAccounts.find((myKey) => myKey.mintingAccount === address)
|
||||
const findMyMintingRecipient = this.listAccounts.find((myKey) => myKey.recipientAccount === address)
|
||||
const findRemovedSponsorsKey = this.listAccounts.filter((my) => my.address)
|
||||
|
||||
if (findMyMintingAccount === undefined) {
|
||||
this.check1 = false
|
||||
} else {
|
||||
this.check1 = true
|
||||
}
|
||||
|
||||
if (findMyMintingRecipient === undefined) {
|
||||
this.check2 = false
|
||||
} else {
|
||||
this.check2 = true
|
||||
}
|
||||
|
||||
if (findRemovedSponsorsKey.length > 0) {
|
||||
this.removeBlankKey(findRemovedSponsorsKey.publicKey)
|
||||
} else {
|
||||
}
|
||||
} catch (error) {
|
||||
this.errorMsg = this.renderMyErrorMsg1()
|
||||
}
|
||||
}
|
||||
|
||||
removeBlankKey(myPublicKey) {
|
||||
parentEpml.request("apiCall", {
|
||||
url: `/admin/mintingaccounts?apiKey=${this.getApiKey()}`,
|
||||
method: "DELETE",
|
||||
body: myPublicKey,
|
||||
}).then((res) => {
|
||||
if (res === true) {
|
||||
console.log('REMOVED BLANK KEY')
|
||||
} else {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
renderMintingStatus() {
|
||||
if (this.nodeInfo.isMintingPossible === true && this.nodeInfo.isSynchronizing === true) {
|
||||
const addressInfo = window.parent.reduxStore.getState().app.accountInfo.addressInfo
|
||||
const myMintingKey = addressInfo?.error !== 124 && +addressInfo?.level > 0
|
||||
|
||||
if (this.nodeInfo.isMintingPossible === true && this.nodeInfo.isSynchronizing === true && this.check1 === true && this.check2 === true && addressInfo.level > 0) {
|
||||
this.cssStatus = ''
|
||||
return html`<span class="btn btn-sm btn-info float-right">${translate("walletprofile.wp1")}</span>`
|
||||
} else if (this.nodeInfo.isMintingPossible === true && this.nodeInfo.isSynchronizing === false) {
|
||||
} else if (this.nodeInfo.isMintingPossible === true && this.nodeInfo.isSynchronizing === false && this.check1 === true && this.check2 === true && addressInfo.level > 0) {
|
||||
this.cssStatus = ''
|
||||
return html`<span class="btn btn-sm btn-info float-right">${translate("walletprofile.wp1")}</span>`
|
||||
} else if (this.nodeInfo.isMintingPossible === false) {
|
||||
} else if (this.nodeInfo.isMintingPossible === true && this.nodeInfo.isSynchronizing === false && this.check1 === false && this.check2 === true && addressInfo.level == 0 && addressInfo.blocksMinted < 7200) {
|
||||
this.cssStatus = ''
|
||||
return html`<span class="btn btn-sm btn-info float-right">${translate("becomeMinterPage.bchange12")}</span>`
|
||||
} else if (this.check1 === false && this.check2 === false && myMintingKey === true) {
|
||||
return html`<span class="float-right"><start-minting-now></start-minting-now></span>`
|
||||
} else if (myMintingKey === false) {
|
||||
return html`<span class="float-right"><start-minting-now></start-minting-now></span>`
|
||||
}
|
||||
}
|
||||
@ -258,7 +348,6 @@ class OverviewPage extends LitElement {
|
||||
this.coreInfo = data
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Request failed', err)
|
||||
})
|
||||
}
|
||||
|
||||
@ -273,9 +362,14 @@ class OverviewPage extends LitElement {
|
||||
this.myBalance = data
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Request failed', err)
|
||||
})
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
let apiKey = myNode.apiKey
|
||||
return apiKey
|
||||
}
|
||||
}
|
||||
window.customElements.define('overview-page', OverviewPage)
|
||||
|
||||
@ -288,12 +382,11 @@ class StartMintingNow extends LitElement {
|
||||
status: { type: Number },
|
||||
timer: { type: Number },
|
||||
privateRewardShareKey: { type: String }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
return [css`
|
||||
p, h1 {
|
||||
color: var(--black)
|
||||
}
|
||||
@ -423,25 +516,24 @@ class StartMintingNow extends LitElement {
|
||||
.message-error {
|
||||
color: var(--error);
|
||||
}
|
||||
`,
|
||||
];
|
||||
`]
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.mintingAccountData = [];
|
||||
this.errorMsg = '';
|
||||
this.openDialogRewardShare = false;
|
||||
this.status = 0;
|
||||
this.privateRewardShareKey = "";
|
||||
super()
|
||||
this.mintingAccountData = []
|
||||
this.errorMsg = ''
|
||||
this.openDialogRewardShare = false
|
||||
this.status = 0
|
||||
this.privateRewardShareKey = ""
|
||||
}
|
||||
|
||||
render() {
|
||||
return html` ${this.renderStartMintingButton()} `;
|
||||
return html`${this.renderStartMintingButton()}`
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.getMintingAcccounts();
|
||||
this.getMintingAcccounts()
|
||||
}
|
||||
|
||||
renderErrorMsg1() {
|
||||
@ -465,16 +557,15 @@ class StartMintingNow extends LitElement {
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
const url = `${nodeUrl}/admin/mintingaccounts`
|
||||
try {
|
||||
const res = await fetch(url);
|
||||
const res = await fetch(url)
|
||||
const mintingAccountData = await res.json()
|
||||
|
||||
this.mintingAccountData = mintingAccountData
|
||||
} catch (error) {
|
||||
this.errorMsg = this.renderErrorMsg1()
|
||||
}
|
||||
}
|
||||
|
||||
async changeStatus(value){
|
||||
async changeStatus(value) {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
this.status = value
|
||||
@ -509,7 +600,7 @@ class StartMintingNow extends LitElement {
|
||||
}
|
||||
} catch (error) {
|
||||
this.errorMsg = this.renderErrorMsg2()
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
@ -540,7 +631,7 @@ class StartMintingNow extends LitElement {
|
||||
}
|
||||
|
||||
if (!stop) {
|
||||
stop = true;
|
||||
stop = true
|
||||
try {
|
||||
const address = window.parent.reduxStore.getState().app?.selectedAddress?.address
|
||||
const myRewardShareArray = await rewardShares(address)
|
||||
@ -554,7 +645,7 @@ class StartMintingNow extends LitElement {
|
||||
}
|
||||
stop = false
|
||||
}
|
||||
};
|
||||
}
|
||||
interval = setInterval(getAnswer, 5000)
|
||||
}
|
||||
|
||||
@ -563,14 +654,14 @@ class StartMintingNow extends LitElement {
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
const mintingAccountData = this.mintingAccountData
|
||||
const addressInfo = window.parent.reduxStore.getState().app.accountInfo.addressInfo
|
||||
const address = window.parent.reduxStore.getState().app?.selectedAddress?.address
|
||||
const nonce = window.parent.reduxStore.getState().app?.selectedAddress?.nonce
|
||||
const publicAddress = window.parent.reduxStore.getState().app?.selectedAddress ?.base58PublicKey
|
||||
const address = window.parent.reduxStore.getState().app.selectedAddress.address
|
||||
const nonce = window.parent.reduxStore.getState().app.selectedAddress.nonce
|
||||
const publicAddress = window.parent.reduxStore.getState().app.selectedAddress.base58PublicKey
|
||||
const findMintingAccount = mintingAccountData.find((ma) => ma.mintingAccount === address)
|
||||
const isMinterButKeyMintingKeyNotAssigned = addressInfo?.error !== 124 && addressInfo?.level >= 1 && !findMintingAccount
|
||||
const isMinterButKeyMintingKeyNotAssigned = addressInfo.error !== 124 && addressInfo.level >= 1 && !findMintingAccount
|
||||
|
||||
const makeTransactionRequest = async (lastRef) => {
|
||||
let mylastRef = lastRef;
|
||||
let mylastRef = lastRef
|
||||
let rewarddialog1 = get('transactions.rewarddialog1')
|
||||
let rewarddialog2 = get('transactions.rewarddialog2')
|
||||
let rewarddialog3 = get('transactions.rewarddialog3')
|
||||
@ -586,26 +677,22 @@ class StartMintingNow extends LitElement {
|
||||
rewarddialog1: rewarddialog1,
|
||||
rewarddialog2: rewarddialog2,
|
||||
rewarddialog3: rewarddialog3,
|
||||
rewarddialog4: rewarddialog4,
|
||||
rewarddialog4: rewarddialog4
|
||||
},
|
||||
disableModal: true,
|
||||
disableModal: true
|
||||
})
|
||||
return myTxnrequest
|
||||
}
|
||||
|
||||
const getTxnRequestResponse = (txnResponse) => {
|
||||
let err6string = get('rewardsharepage.rchange21');
|
||||
if (txnResponse?.extraData?.rewardSharePrivateKey && (txnResponse?.data?.message?.includes('multiple') || txnResponse?.data?.message?.includes('SELF_SHARE_EXISTS'))) {
|
||||
let err6string = get('rewardsharepage.rchange21')
|
||||
if (txnResponse.extraData.rewardSharePrivateKey && (txnResponse.data.message.includes('multiple') || txnResponse.data.message.includes('SELF_SHARE_EXISTS'))) {
|
||||
return err6string
|
||||
}
|
||||
if (txnResponse.success === false && txnResponse.message) {
|
||||
throw (txnResponse);
|
||||
} else if (
|
||||
txnResponse.success === true &&
|
||||
!txnResponse.data.error
|
||||
) {
|
||||
|
||||
return err6string;
|
||||
throw (txnResponse)
|
||||
} else if (txnResponse.success === true && !txnResponse.data.error) {
|
||||
return err6string
|
||||
} else {
|
||||
throw (txnResponse)
|
||||
}
|
||||
@ -617,36 +704,35 @@ class StartMintingNow extends LitElement {
|
||||
|
||||
let myTransaction = await makeTransactionRequest(lastRef)
|
||||
|
||||
getTxnRequestResponse(myTransaction);
|
||||
return myTransaction?.extraData?.rewardSharePrivateKey
|
||||
getTxnRequestResponse(myTransaction)
|
||||
return myTransaction.extraData.rewardSharePrivateKey
|
||||
}
|
||||
|
||||
const getLastRef = async () => {
|
||||
const url = `${nodeUrl}/addresses/lastreference/${address}`
|
||||
const res = await fetch(url)
|
||||
const data = await res.text()
|
||||
return data
|
||||
let myRef = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/addresses/lastreference/${address}`
|
||||
})
|
||||
return myRef
|
||||
}
|
||||
|
||||
const startMinting = async () => {
|
||||
this.openDialogRewardShare = true
|
||||
this.errorMsg = ''
|
||||
const address = window.parent.reduxStore.getState().app?.selectedAddress?.address
|
||||
|
||||
const findMintingAccountsFromUser = this.mintingAccountData.filter((ma) => ma.recipientAccount === address && ma.mintingAccount === address)
|
||||
|
||||
if(findMintingAccountsFromUser.length > 2){
|
||||
if(findMintingAccountsFromUser.length > 2) {
|
||||
this.errorMsg = translate("startminting.smchange10")
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
this.privateRewardShareKey = await createSponsorshipKey()
|
||||
this.confirmRelationship(publicAddress)
|
||||
} catch (error) {
|
||||
console.log({ error })
|
||||
this.errorMsg = error?.data?.message || this.renderErrorMsg4()
|
||||
return;
|
||||
this.errorMsg = error.data.message || this.renderErrorMsg4()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -670,7 +756,7 @@ class StartMintingNow extends LitElement {
|
||||
${this.openDialogRewardShare ? html`
|
||||
<div class="dialogCustom">
|
||||
<div class="dialogCustomInner">
|
||||
<div class="dialog-header" >
|
||||
<div class="dialog-header">
|
||||
<div class="row">
|
||||
<h1>In progress</h1>
|
||||
<div class=${`smallLoading marginLoader ${this.status > 3 && 'hide'}`}></div>
|
||||
@ -724,24 +810,28 @@ class StartMintingNow extends LitElement {
|
||||
</div>
|
||||
<div class="modalFooter">
|
||||
${this.errorMsg || this.status === 5 ? html`
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${() => {
|
||||
this.openDialogRewardShare = false
|
||||
this.errorMsg = ''
|
||||
}}
|
||||
class="red"
|
||||
>
|
||||
${translate("general.close")}
|
||||
</mwc-button>
|
||||
` : '' }
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${() => {
|
||||
this.openDialogRewardShare = false
|
||||
this.errorMsg = ''
|
||||
}}
|
||||
class="red"
|
||||
>
|
||||
${translate("general.close")}
|
||||
</mwc-button>
|
||||
` : '' }
|
||||
</div>
|
||||
</div>
|
||||
` : ""}
|
||||
` : html`
|
||||
<div class="start-minting-wrapper">
|
||||
<a href="../become-minter/index.html">
|
||||
<my-button label="${translate('tabmenu.tm2')}"></my-button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
` : ""}
|
||||
` : ''}
|
||||
`;
|
||||
`}
|
||||
`
|
||||
}
|
||||
}
|
||||
window.customElements.define('start-minting-now', StartMintingNow)
|
||||
@ -750,8 +840,8 @@ class MyButton extends LitElement {
|
||||
static properties = {
|
||||
onClick: { type: Function },
|
||||
isLoading: { type: Boolean },
|
||||
label: { type: String },
|
||||
};
|
||||
label: { type: String }
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
vaadin-button {
|
||||
@ -769,13 +859,13 @@ class MyButton extends LitElement {
|
||||
vaadin-button:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
`;
|
||||
`
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.onClick = () => {};
|
||||
this.isLoading = false;
|
||||
this.label = '';
|
||||
super()
|
||||
this.onClick = () => {}
|
||||
this.isLoading = false
|
||||
this.label = ''
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -788,7 +878,7 @@ class MyButton extends LitElement {
|
||||
? html`${this.label}`
|
||||
: html`<paper-spinner-lite active></paper-spinner-lite>`}
|
||||
</vaadin-button>
|
||||
`;
|
||||
`
|
||||
}
|
||||
}
|
||||
customElements.define('my-button', MyButton)
|
@ -180,7 +180,6 @@ class Puzzles extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
|
||||
@ -308,7 +307,7 @@ class Puzzles extends LitElement {
|
||||
|
||||
this.puzzles = _puzzles;
|
||||
|
||||
setTimeout(updatePuzzles, 20000)
|
||||
setTimeout(updatePuzzles, 60000)
|
||||
}
|
||||
|
||||
let configLoaded = false
|
||||
@ -330,6 +329,18 @@ class Puzzles extends LitElement {
|
||||
})
|
||||
})
|
||||
parentEpml.imReady()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
|
@ -544,7 +544,6 @@ class QApps extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
this.showapps()
|
||||
@ -624,6 +623,18 @@ class QApps extends LitElement {
|
||||
})
|
||||
})
|
||||
parentEpml.imReady()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
|
@ -20,10 +20,9 @@ import { Loader } from '../../../utils/loader.js';
|
||||
import { QORT_DECIMALS } from '../../../../../crypto/api/constants'
|
||||
import nacl from '../../../../../crypto/api/deps/nacl-fast.js'
|
||||
import ed2curve from '../../../../../crypto/api/deps/ed2curve.js'
|
||||
import { mimeToExtensionMap } from '../../components/qdn-action-constants'
|
||||
import { base64ToUint8Array, encryptData, fileToBase64, uint8ArrayToBase64 } from '../../components/qdn-action-encryption'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
import { mimeToExtensionMap } from '../../components/qdn-action-constants';
|
||||
import { base64ToUint8Array, decryptDeprecatedSingle, decryptGroupData, encryptDataGroup, fileToBase64, uint8ArrayStartsWith, uint8ArrayToBase64 } from '../../components/qdn-action-encryption';
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
|
||||
|
||||
class WebBrowser extends LitElement {
|
||||
static get properties() {
|
||||
@ -630,57 +629,52 @@ class WebBrowser extends LitElement {
|
||||
}
|
||||
|
||||
case actions.DECRYPT_DATA: {
|
||||
const requiredFields = ['encryptedData', 'publicKey'];
|
||||
const missingFields = [];
|
||||
|
||||
requiredFields.forEach((field) => {
|
||||
if (!data[field]) {
|
||||
missingFields.push(field);
|
||||
}
|
||||
});
|
||||
const { encryptedData, publicKey } = data
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
const missingFieldsString = missingFields.join(', ');
|
||||
const errorMsg = `Missing fields: ${missingFieldsString}`
|
||||
try {
|
||||
let data = {};
|
||||
if (!encryptedData) {
|
||||
const errorMsg = `Missing fields: encryptedData`
|
||||
|
||||
data['error'] = errorMsg;
|
||||
response = JSON.stringify(data);
|
||||
break
|
||||
|
||||
}
|
||||
const uint8Array = base64ToUint8Array(encryptedData)
|
||||
const startsWithQortalEncryptedData = uint8ArrayStartsWith(uint8Array, "qortalEncryptedData");
|
||||
if (startsWithQortalEncryptedData) {
|
||||
|
||||
if (!publicKey) {
|
||||
const errorMsg = `Missing fields: publicKey`
|
||||
|
||||
data['error'] = errorMsg;
|
||||
response = JSON.stringify(data);
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
const decryptedDataToBase64 = decryptDeprecatedSingle(uint8Array, publicKey)
|
||||
response = JSON.stringify(decryptedDataToBase64);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
const startsWithQortalGroupEncryptedData = uint8ArrayStartsWith(uint8Array, "qortalGroupEncryptedData");
|
||||
if (startsWithQortalGroupEncryptedData) {
|
||||
|
||||
const decryptedData = decryptGroupData(encryptedData)
|
||||
const decryptedDataToBase64 = uint8ArrayToBase64(decryptedData)
|
||||
response = JSON.stringify(decryptedDataToBase64);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
const errorMsg = "Unable to decrypt"
|
||||
data['error'] = errorMsg;
|
||||
response = JSON.stringify(data);
|
||||
break
|
||||
}
|
||||
const { encryptedData, publicKey } = data
|
||||
|
||||
|
||||
try {
|
||||
const uint8Array = base64ToUint8Array(encryptedData)
|
||||
const combinedData = uint8Array
|
||||
const str = "qortalEncryptedData";
|
||||
const strEncoder = new TextEncoder();
|
||||
const strUint8Array = strEncoder.encode(str);
|
||||
|
||||
const strData = combinedData.slice(0, strUint8Array.length);
|
||||
const nonce = combinedData.slice(strUint8Array.length, strUint8Array.length + 24);
|
||||
const _encryptedData = combinedData.slice(strUint8Array.length + 24);
|
||||
|
||||
const privateKey = window.parent.reduxStore.getState().app.selectedAddress.keyPair.privateKey
|
||||
const _publicKey = window.parent.Base58.decode(publicKey)
|
||||
|
||||
if (!privateKey || !_publicKey) {
|
||||
data['error'] = "Unable to retrieve keys"
|
||||
response = JSON.stringify(data);
|
||||
break
|
||||
}
|
||||
|
||||
const convertedPrivateKey = ed2curve.convertSecretKey(privateKey)
|
||||
const convertedPublicKey = ed2curve.convertPublicKey(_publicKey)
|
||||
const sharedSecret = new Uint8Array(32);
|
||||
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey)
|
||||
|
||||
const _chatEncryptionSeed = new window.parent.Sha256().process(sharedSecret).finish().result
|
||||
const _decryptedData = nacl.secretbox.open(_encryptedData, nonce, _chatEncryptionSeed)
|
||||
const decryptedDataToBase64 = uint8ArrayToBase64(_decryptedData)
|
||||
response = JSON.stringify(decryptedDataToBase64);
|
||||
|
||||
break;
|
||||
} catch (error) {
|
||||
|
||||
const data = {};
|
||||
@ -690,6 +684,7 @@ class WebBrowser extends LitElement {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
case actions.GET_LIST_ITEMS: {
|
||||
const requiredFields = ['list_name'];
|
||||
const missingFields = [];
|
||||
@ -984,9 +979,9 @@ class WebBrowser extends LitElement {
|
||||
identifier = 'default';
|
||||
}
|
||||
|
||||
if (data.encrypt && !data.recipientPublicKey) {
|
||||
if (data.encrypt && (!data.publicKeys || (Array.isArray(data.publicKeys) && data.publicKeys.length === 0))) {
|
||||
let data = {};
|
||||
data['error'] = "Encrypting data requires the recipient's public key";
|
||||
data['error'] = "Encrypting data requires public keys";
|
||||
response = JSON.stringify(data);
|
||||
break
|
||||
}
|
||||
@ -996,14 +991,17 @@ class WebBrowser extends LitElement {
|
||||
response = JSON.stringify(data);
|
||||
break
|
||||
}
|
||||
if (data.file) {
|
||||
data64 = await fileToBase64(data.file)
|
||||
}
|
||||
|
||||
if (data.encrypt) {
|
||||
try {
|
||||
const encryptDataResponse = encryptData({
|
||||
data64, recipientPublicKey: data.recipientPublicKey
|
||||
const encryptDataResponse = encryptDataGroup({
|
||||
data64, publicKeys: data.publicKeys
|
||||
})
|
||||
if (encryptDataResponse.encryptedData) {
|
||||
data64 = encryptDataResponse.encryptedData
|
||||
if (encryptDataResponse) {
|
||||
data64 = encryptDataResponse
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
@ -1017,6 +1015,7 @@ class WebBrowser extends LitElement {
|
||||
}
|
||||
|
||||
|
||||
|
||||
const res2 = await showModalAndWait(
|
||||
actions.PUBLISH_QDN_RESOURCE,
|
||||
{
|
||||
@ -1109,9 +1108,9 @@ class WebBrowser extends LitElement {
|
||||
response = JSON.stringify(data);
|
||||
break
|
||||
}
|
||||
if (data.encrypt && !data.recipientPublicKey) {
|
||||
if (data.encrypt && (!data.publicKeys || (Array.isArray(data.publicKeys) && data.publicKeys.length === 0))) {
|
||||
let data = {};
|
||||
data['error'] = "Encrypting data requires the recipient's public key";
|
||||
data['error'] = "Encrypting data requires public keys";
|
||||
response = JSON.stringify(data);
|
||||
break
|
||||
}
|
||||
@ -1169,14 +1168,19 @@ class WebBrowser extends LitElement {
|
||||
if (!data.encrypt && service.endsWith("_PRIVATE")) {
|
||||
throw new Error("Only encrypted data can go into private services")
|
||||
}
|
||||
if (data.file) {
|
||||
data64 = await fileToBase64(data.file)
|
||||
}
|
||||
|
||||
|
||||
if (data.encrypt) {
|
||||
try {
|
||||
const encryptDataResponse = encryptData({
|
||||
data64, recipientPublicKey: data.recipientPublicKey
|
||||
|
||||
const encryptDataResponse = encryptDataGroup({
|
||||
data64, publicKeys: data.publicKeys
|
||||
})
|
||||
if (encryptDataResponse.encryptedData) {
|
||||
data64 = encryptDataResponse.encryptedData
|
||||
if (encryptDataResponse) {
|
||||
data64 = encryptDataResponse
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
@ -2669,6 +2673,18 @@ class WebBrowser extends LitElement {
|
||||
});
|
||||
}
|
||||
});
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
|
@ -441,7 +441,6 @@ class DataManagement extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
this.showManagement()
|
||||
@ -494,6 +493,18 @@ class DataManagement extends LitElement {
|
||||
})
|
||||
})
|
||||
parentEpml.imReady()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
|
@ -318,7 +318,6 @@ class PublishData extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
|
||||
@ -343,6 +342,18 @@ class PublishData extends LitElement {
|
||||
window.parent.electronAPI.showMyMenu()
|
||||
})
|
||||
}
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
|
@ -398,7 +398,6 @@ class Websites extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
this.showWebsites()
|
||||
@ -478,6 +477,18 @@ class Websites extends LitElement {
|
||||
})
|
||||
})
|
||||
parentEpml.imReady()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
|
@ -211,7 +211,6 @@ class RewardShare extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
|
||||
@ -238,12 +237,13 @@ class RewardShare extends LitElement {
|
||||
}
|
||||
|
||||
const updateRewardshares = () => {
|
||||
this.rewardShares = []
|
||||
parentEpml.request('apiCall', {
|
||||
url: `/addresses/rewardshares?involving=${this.selectedAddress.address}`
|
||||
}).then(res => {
|
||||
setTimeout(() => { this.rewardShares = res }, 1)
|
||||
this.rewardShares = res
|
||||
})
|
||||
setTimeout(updateRewardshares, this.config.user.nodeSettings.pingInterval)
|
||||
setTimeout(updateRewardshares, 60000)
|
||||
}
|
||||
|
||||
let configLoaded = false
|
||||
@ -266,6 +266,18 @@ class RewardShare extends LitElement {
|
||||
})
|
||||
|
||||
parentEpml.imReady()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
changeTheme() {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,20 +7,16 @@ let closeGracefully = false
|
||||
let isCalled = false
|
||||
let retryOnClose = false
|
||||
let blockFirstCall = true
|
||||
|
||||
let nodeStatusSocketObject
|
||||
let nodeStatusSocketTimeout
|
||||
let nodeStatusSocketcloseGracefully = false
|
||||
let nodeStatusCount = 0
|
||||
let nodeStatusRetryOnClose = false
|
||||
let nodeStateCall = false
|
||||
|
||||
let isLoggedIn = false
|
||||
|
||||
let oldAccountInfo
|
||||
|
||||
parentEpml.subscribe('logged_in', loggedIn => {
|
||||
|
||||
if (loggedIn === 'true') {
|
||||
isLoggedIn = true
|
||||
} else {
|
||||
@ -29,35 +25,28 @@ parentEpml.subscribe('logged_in', loggedIn => {
|
||||
})
|
||||
|
||||
const setAccountInfo = async (addr) => {
|
||||
|
||||
const names = await parentEpml.request('apiCall', {
|
||||
url: `/names/address/${addr}`
|
||||
})
|
||||
const addressInfo = await parentEpml.request('apiCall', {
|
||||
url: `/addresses/${addr}`
|
||||
})
|
||||
|
||||
let accountInfo = {
|
||||
names: names,
|
||||
addressInfo: addressInfo
|
||||
}
|
||||
|
||||
if (window.parent._.isEqual(oldAccountInfo, accountInfo) === true) {
|
||||
|
||||
return
|
||||
} else {
|
||||
|
||||
parentEpml.request('setAccountInfo', accountInfo)
|
||||
oldAccountInfo = accountInfo
|
||||
}
|
||||
}
|
||||
|
||||
const doNodeInfo = async () => {
|
||||
|
||||
const nodeInfo = await parentEpml.request('apiCall', {
|
||||
url: '/admin/info'
|
||||
})
|
||||
|
||||
parentEpml.request('updateNodeInfo', nodeInfo)
|
||||
}
|
||||
|
||||
@ -65,71 +54,57 @@ let initStateCount = 0
|
||||
let oldState
|
||||
|
||||
const closeSockets = () => {
|
||||
|
||||
socketObject.close();
|
||||
socketObject.close()
|
||||
closeGracefully = true
|
||||
|
||||
nodeStatusSocketObject.close();
|
||||
nodeStatusSocketObject.close()
|
||||
nodeStatusSocketcloseGracefully = true
|
||||
}
|
||||
|
||||
export const startConfigWatcher = () => {
|
||||
|
||||
parentEpml.ready().then(() => {
|
||||
parentEpml.subscribe('node_config', c => {
|
||||
|
||||
if (initStateCount === 0) {
|
||||
let _oldState = JSON.parse(c)
|
||||
oldState = { node: _oldState.node, knownNodes: _oldState.knownNodes }
|
||||
initStateCount = initStateCount + 1
|
||||
|
||||
nodeStateCall = true
|
||||
isCalled = true
|
||||
socketObject !== undefined ? closeSockets() : undefined;
|
||||
nodeStatusSocketObject !== undefined ? closeSockets() : undefined;
|
||||
socketObject !== undefined ? closeSockets() : undefined
|
||||
nodeStatusSocketObject !== undefined ? closeSockets() : undefined
|
||||
initNodeStatusCall(oldState)
|
||||
pingactiveBlockSocket()
|
||||
|
||||
// Call doNodeInfo
|
||||
doNodeInfo()
|
||||
}
|
||||
|
||||
let _newState = JSON.parse(c);
|
||||
let _newState = JSON.parse(c)
|
||||
let newState = { node: _newState.node, knownNodes: _newState.knownNodes }
|
||||
|
||||
if (window.parent._.isEqual(oldState, newState) === true) {
|
||||
return
|
||||
} else {
|
||||
oldState = newState
|
||||
nodeStateCall = true
|
||||
isCalled = true
|
||||
socketObject !== undefined ? closeSockets() : undefined;
|
||||
nodeStatusSocketObject !== undefined ? closeSockets() : undefined;
|
||||
socketObject !== undefined ? closeSockets() : undefined
|
||||
nodeStatusSocketObject !== undefined ? closeSockets() : undefined
|
||||
initNodeStatusCall(newState)
|
||||
pingactiveBlockSocket()
|
||||
|
||||
// Call doNodeInfo
|
||||
doNodeInfo()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
parentEpml.imReady()
|
||||
}
|
||||
|
||||
const processBlock = (blockObject) => {
|
||||
|
||||
parentEpml.request('updateBlockInfo', blockObject)
|
||||
}
|
||||
|
||||
const doNodeStatus = async (nodeStatusObject) => {
|
||||
|
||||
parentEpml.request('updateNodeStatus', nodeStatusObject)
|
||||
}
|
||||
|
||||
|
||||
const initNodeStatusCall = (nodeConfig) => {
|
||||
|
||||
if (nodeConfig.node == 0) {
|
||||
pingNodeStatusSocket()
|
||||
} else if (nodeConfig.node == 1) {
|
||||
@ -143,193 +118,131 @@ const initNodeStatusCall = (nodeConfig) => {
|
||||
}
|
||||
|
||||
const initBlockSocket = () => {
|
||||
|
||||
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
let nodeUrl = myNode.domain + ":" + myNode.port
|
||||
|
||||
let activeBlockSocketLink
|
||||
|
||||
if (window.parent.location.protocol === "https:") {
|
||||
|
||||
activeBlockSocketLink = `wss://${nodeUrl}/websockets/blocks`;
|
||||
activeBlockSocketLink = `wss://${nodeUrl}/websockets/blocks`
|
||||
} else {
|
||||
|
||||
activeBlockSocketLink = `ws://${nodeUrl}/websockets/blocks`;
|
||||
activeBlockSocketLink = `ws://${nodeUrl}/websockets/blocks`
|
||||
}
|
||||
|
||||
const activeBlockSocket = new WebSocket(activeBlockSocketLink);
|
||||
|
||||
const activeBlockSocket = new WebSocket(activeBlockSocketLink)
|
||||
// Open Connection
|
||||
activeBlockSocket.onopen = (e) => {
|
||||
|
||||
console.log(`[SOCKET-BLOCKS]: Connected.`);
|
||||
closeGracefully = false
|
||||
socketObject = activeBlockSocket
|
||||
|
||||
initial = initial + 1
|
||||
}
|
||||
|
||||
// Message Event
|
||||
activeBlockSocket.onmessage = (e) => {
|
||||
|
||||
processBlock(JSON.parse(e.data));
|
||||
|
||||
processBlock(JSON.parse(e.data))
|
||||
if (isLoggedIn) {
|
||||
|
||||
// Call Set Account Info...
|
||||
setAccountInfo(window.parent.reduxStore.getState().app.selectedAddress.address)
|
||||
}
|
||||
}
|
||||
|
||||
// Closed Event
|
||||
activeBlockSocket.onclose = () => {
|
||||
|
||||
console.log(`[SOCKET-BLOCKS]: CLOSED`);
|
||||
|
||||
processBlock({});
|
||||
processBlock({})
|
||||
blockFirstCall = true
|
||||
clearInterval(activeBlockSocketTimeout)
|
||||
|
||||
if (closeGracefully === false && initial <= 52) {
|
||||
|
||||
if (initial <= 52) {
|
||||
|
||||
retryOnClose = true
|
||||
setTimeout(pingactiveBlockSocket, 10000)
|
||||
initial = initial + 1
|
||||
} else {
|
||||
|
||||
// ... Stop retrying...
|
||||
retryOnClose = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error Event
|
||||
activeBlockSocket.onerror = (e) => {
|
||||
|
||||
console.log(`[SOCKET-BLOCKS]: ${e.type}`);
|
||||
blockFirstCall = true
|
||||
processBlock({});
|
||||
processBlock({})
|
||||
}
|
||||
|
||||
if (blockFirstCall) {
|
||||
|
||||
parentEpml.request('apiCall', {
|
||||
url: '/blocks/last'
|
||||
}).then(res => {
|
||||
|
||||
processBlock(res)
|
||||
blockFirstCall = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const pingactiveBlockSocket = () => {
|
||||
|
||||
if (isCalled) {
|
||||
|
||||
isCalled = false
|
||||
|
||||
initBlockSocket()
|
||||
activeBlockSocketTimeout = setTimeout(pingactiveBlockSocket, 295000)
|
||||
} else if (retryOnClose) {
|
||||
|
||||
retryOnClose = false
|
||||
clearTimeout(activeBlockSocketTimeout)
|
||||
initBlockSocket()
|
||||
isCalled = true
|
||||
activeBlockSocketTimeout = setTimeout(pingactiveBlockSocket, 295000)
|
||||
} else {
|
||||
|
||||
socketObject.send("non-integer ping")
|
||||
activeBlockSocketTimeout = setTimeout(pingactiveBlockSocket, 295000)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const initNodeStatusSocket = () => {
|
||||
|
||||
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
let nodeUrl = myNode.domain + ":" + myNode.port
|
||||
|
||||
let activeNodeStatusSocketLink
|
||||
|
||||
if (window.parent.location.protocol === "https:") {
|
||||
|
||||
activeNodeStatusSocketLink = `wss://${nodeUrl}/websockets/admin/status`;
|
||||
activeNodeStatusSocketLink = `wss://${nodeUrl}/websockets/admin/status`
|
||||
} else {
|
||||
|
||||
activeNodeStatusSocketLink = `ws://${nodeUrl}/websockets/admin/status`;
|
||||
activeNodeStatusSocketLink = `ws://${nodeUrl}/websockets/admin/status`
|
||||
}
|
||||
|
||||
const activeNodeStatusSocket = new WebSocket(activeNodeStatusSocketLink);
|
||||
|
||||
const activeNodeStatusSocket = new WebSocket(activeNodeStatusSocketLink)
|
||||
// Open Connection
|
||||
activeNodeStatusSocket.onopen = (e) => {
|
||||
|
||||
console.log(`[SOCKET-NODE-STATUS]: Connected.`);
|
||||
nodeStatusSocketcloseGracefully = false
|
||||
nodeStatusSocketObject = activeNodeStatusSocket
|
||||
|
||||
nodeStatusCount = nodeStatusCount + 1
|
||||
}
|
||||
|
||||
// Message Event
|
||||
activeNodeStatusSocket.onmessage = (e) => {
|
||||
|
||||
doNodeStatus(JSON.parse(e.data))
|
||||
}
|
||||
|
||||
// Closed Event
|
||||
activeNodeStatusSocket.onclose = () => {
|
||||
|
||||
console.log(`[SOCKET-NODE-STATUS]: CLOSED`);
|
||||
|
||||
doNodeStatus({});
|
||||
doNodeStatus({})
|
||||
clearInterval(nodeStatusSocketTimeout)
|
||||
|
||||
if (nodeStatusSocketcloseGracefully === false && nodeStatusCount <= 52) {
|
||||
|
||||
if (nodeStatusCount <= 52) {
|
||||
|
||||
nodeStatusRetryOnClose = true
|
||||
setTimeout(pingNodeStatusSocket, 10000)
|
||||
nodeStatusCount = nodeStatusCount + 1
|
||||
} else {
|
||||
|
||||
// ... Stop retrying...
|
||||
nodeStatusRetryOnClose = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error Event
|
||||
activeNodeStatusSocket.onerror = (e) => {
|
||||
|
||||
console.log(`[SOCKET-NODE-STATUS]: ${e.type}`);
|
||||
doNodeStatus({});
|
||||
doNodeStatus({})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const pingNodeStatusSocket = () => {
|
||||
|
||||
if (nodeStateCall) {
|
||||
|
||||
clearTimeout(nodeStatusSocketTimeout)
|
||||
initNodeStatusSocket()
|
||||
nodeStateCall = false
|
||||
nodeStatusSocketTimeout = setTimeout(pingNodeStatusSocket, 295000)
|
||||
} else if (nodeStatusRetryOnClose) {
|
||||
|
||||
nodeStatusRetryOnClose = false
|
||||
clearTimeout(nodeStatusSocketTimeout)
|
||||
initNodeStatusSocket()
|
||||
nodeStatusSocketTimeout = setTimeout(pingNodeStatusSocket, 295000)
|
||||
} else {
|
||||
|
||||
nodeStatusSocketObject.send("non-integer ping")
|
||||
nodeStatusSocketTimeout = setTimeout(pingNodeStatusSocket, 295000)
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ const sortActiveChat = (activeChatObject, localChatHeads) => {
|
||||
let results = newActiveChats.filter(newChat => {
|
||||
let value = oldActiveChats.some(oldChat => newChat.timestamp === oldChat.timestamp)
|
||||
return !value
|
||||
});
|
||||
})
|
||||
|
||||
results.forEach(chat => {
|
||||
|
||||
@ -103,8 +103,6 @@ const chatHeadWatcher = (activeChats) => {
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,13 +126,13 @@ parentEpml.subscribe('logged_in', async isLoggedIn => {
|
||||
|
||||
if (window.parent.location.protocol === "https:") {
|
||||
|
||||
activeChatSocketLink = `wss://${nodeUrl}/websockets/chat/active/${window.parent.reduxStore.getState().app.selectedAddress.address}?encoding=BASE64`;
|
||||
activeChatSocketLink = `wss://${nodeUrl}/websockets/chat/active/${window.parent.reduxStore.getState().app.selectedAddress.address}?encoding=BASE64`
|
||||
} else {
|
||||
|
||||
activeChatSocketLink = `ws://${nodeUrl}/websockets/chat/active/${window.parent.reduxStore.getState().app.selectedAddress.address}?encoding=BASE64`;
|
||||
activeChatSocketLink = `ws://${nodeUrl}/websockets/chat/active/${window.parent.reduxStore.getState().app.selectedAddress.address}?encoding=BASE64`
|
||||
}
|
||||
|
||||
const activeChatSocket = new WebSocket(activeChatSocketLink);
|
||||
const activeChatSocket = new WebSocket(activeChatSocketLink)
|
||||
|
||||
// Open Connection
|
||||
activeChatSocket.onopen = () => {
|
||||
@ -147,16 +145,14 @@ parentEpml.subscribe('logged_in', async isLoggedIn => {
|
||||
// Message Event
|
||||
activeChatSocket.onmessage = (e) => {
|
||||
if (e.data === 'pong') {
|
||||
clearTimeout(timeoutId);
|
||||
clearTimeout(timeoutId)
|
||||
activeChatSocketTimeout = setTimeout(pingActiveChatSocket, 45000)
|
||||
return
|
||||
}
|
||||
try {
|
||||
chatHeadWatcher(JSON.parse(e.data))
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Closed Event
|
||||
@ -171,8 +167,6 @@ parentEpml.subscribe('logged_in', async isLoggedIn => {
|
||||
|
||||
// Error Event
|
||||
activeChatSocket.onerror = (e) => {
|
||||
|
||||
console.log(`[SOCKET]: ${e.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,9 +191,9 @@ parentEpml.subscribe('logged_in', async isLoggedIn => {
|
||||
|
||||
socketObject.send('ping')
|
||||
timeoutId = setTimeout(() => {
|
||||
socketObject.close();
|
||||
socketObject.close()
|
||||
clearTimeout(activeChatSocketTimeout)
|
||||
}, 5000);
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -2100,7 +2100,6 @@ class TradeBotPortal extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
let _this = this
|
||||
|
||||
this.changeTheme()
|
||||
@ -2281,6 +2280,18 @@ class TradeBotPortal extends LitElement {
|
||||
this.dgbTradebook()
|
||||
this.rvnTradebook()
|
||||
this.arrrTradebook()
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
renderAutoLockButton() {
|
||||
|
@ -1417,7 +1417,6 @@ class TradePortal extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
let _this = this
|
||||
|
||||
this.changeTheme()
|
||||
@ -1505,42 +1504,42 @@ class TradePortal extends LitElement {
|
||||
|
||||
const getQortBtcPrice = () => {
|
||||
parentEpml.request("apiCall", { url: `/crosschain/price/BITCOIN?inverse=true` }).then((res) => {
|
||||
setTimeout(() => { this.qortbtc = (Number(res) / 1e8).toFixed(8) }, 1)
|
||||
this.qortbtc = (Number(res) / 1e8).toFixed(8)
|
||||
})
|
||||
setTimeout(getQortBtcPrice, 300000)
|
||||
}
|
||||
|
||||
const getQortLtcPrice = () => {
|
||||
parentEpml.request("apiCall", { url: `/crosschain/price/LITECOIN?inverse=true` }).then((res) => {
|
||||
setTimeout(() => { this.qortltc = (Number(res) / 1e8).toFixed(8) }, 1)
|
||||
this.qortltc = (Number(res) / 1e8).toFixed(8)
|
||||
})
|
||||
setTimeout(getQortLtcPrice, 300000)
|
||||
}
|
||||
|
||||
const getQortDogePrice = () => {
|
||||
parentEpml.request("apiCall", { url: `/crosschain/price/DOGECOIN?inverse=true` }).then((res) => {
|
||||
setTimeout(() => { this.qortdoge = (Number(res) / 1e8).toFixed(8) }, 1)
|
||||
this.qortdoge = (Number(res) / 1e8).toFixed(8)
|
||||
})
|
||||
setTimeout(getQortDogePrice, 300000)
|
||||
}
|
||||
|
||||
const getQortDgbPrice = () => {
|
||||
parentEpml.request("apiCall", { url: `/crosschain/price/DIGIBYTE?inverse=true` }).then((res) => {
|
||||
setTimeout(() => { this.qortdgb = (Number(res) / 1e8).toFixed(8) }, 1)
|
||||
this.qortdgb = (Number(res) / 1e8).toFixed(8)
|
||||
})
|
||||
setTimeout(getQortDgbPrice, 300000)
|
||||
}
|
||||
|
||||
const getQortRvnPrice = () => {
|
||||
parentEpml.request("apiCall", { url: `/crosschain/price/RAVENCOIN?inverse=true` }).then((res) => {
|
||||
setTimeout(() => { this.qortrvn = (Number(res) / 1e8).toFixed(8) }, 1)
|
||||
this.qortrvn = (Number(res) / 1e8).toFixed(8)
|
||||
})
|
||||
setTimeout(getQortRvnPrice, 300000)
|
||||
}
|
||||
|
||||
const getQortArrrPrice = () => {
|
||||
parentEpml.request("apiCall", { url: `/crosschain/price/PIRATECHAIN?inverse=true` }).then((res) => {
|
||||
setTimeout(() => { this.qortarrr = (Number(res) / 1e8).toFixed(8) }, 1)
|
||||
this.qortarrr = (Number(res) / 1e8).toFixed(8)
|
||||
})
|
||||
setTimeout(getQortArrrPrice, 300000)
|
||||
}
|
||||
@ -1614,6 +1613,18 @@ class TradePortal extends LitElement {
|
||||
parentEpml.imReady()
|
||||
|
||||
setTimeout(() => this.shadowRoot.querySelector('[slot="vaadin-grid-cell-content-3"]').setAttribute('title', 'Last Seen'), 3000)
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
renderTradeLockButton() {
|
||||
|
@ -2819,7 +2819,6 @@ class MultiWallet extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
this.changeTheme()
|
||||
this.changeLanguage()
|
||||
|
||||
@ -2902,6 +2901,19 @@ class MultiWallet extends LitElement {
|
||||
window.parent.electronAPI.showMyMenu()
|
||||
})
|
||||
}
|
||||
|
||||
this.clearConsole()
|
||||
setInterval(() => {
|
||||
this.clearConsole()
|
||||
}, 60000)
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (!isElectron()) {
|
||||
} else {
|
||||
console.clear()
|
||||
window.parent.electronAPI.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
renderWalletLockButton() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user