Browse Source

Merge pull request #185 from Qortal/master

Update dev branch
qortal-ui-dev
AlphaX-Projects 1 year ago committed by GitHub
parent
commit
b581327c71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      README.md
  2. 3
      core/language/de.json
  3. 3
      core/language/es.json
  4. 3
      core/language/fr.json
  5. 3
      core/language/hindi.json
  6. 3
      core/language/hr.json
  7. 3
      core/language/hu.json
  8. 3
      core/language/it.json
  9. 3
      core/language/jp.json
  10. 3
      core/language/ko.json
  11. 3
      core/language/no.json
  12. 3
      core/language/pl.json
  13. 3
      core/language/pt.json
  14. 3
      core/language/ro.json
  15. 3
      core/language/rs.json
  16. 3
      core/language/ru.json
  17. 3
      core/language/us.json
  18. 3
      core/language/zhc.json
  19. 3
      core/language/zht.json
  20. 29
      core/src/components/app-view.js
  21. 54
      electron.js
  22. 6
      lib/preload.js
  23. 2654
      package-lock.json
  24. 46
      package.json
  25. 12
      plugins/plugins/core/become-minter/become-minter.src.js
  26. 64
      plugins/plugins/core/become-minter/components/not-sponsored.js
  27. 39
      plugins/plugins/core/become-minter/components/yes-sponsored.js
  28. 4
      plugins/plugins/core/components/ChatGifs/ChatGifs.js
  29. 18
      plugins/plugins/core/components/ChatGifs/ChatGifsExplore.js
  30. 2
      plugins/plugins/core/components/ChatGroupInvites.js
  31. 18
      plugins/plugins/core/components/ChatGroupSettings.js
  32. 26
      plugins/plugins/core/components/ChatGroupsManagement.js
  33. 63
      plugins/plugins/core/components/ChatHead.js
  34. 17
      plugins/plugins/core/components/ChatLeaveGroup.js
  35. 2
      plugins/plugins/core/components/ChatMessage.js
  36. 60
      plugins/plugins/core/components/ChatModals.js
  37. 1191
      plugins/plugins/core/components/ChatPage.js
  38. 4
      plugins/plugins/core/components/ChatRightPanel.js
  39. 538
      plugins/plugins/core/components/ChatScroller.js
  40. 72
      plugins/plugins/core/components/ChatSearchResults.js
  41. 1
      plugins/plugins/core/components/ChatSelect.js
  42. 5
      plugins/plugins/core/components/ChatSideNavHeads.js
  43. 53
      plugins/plugins/core/components/ChatTextEditor copy.js
  44. 16
      plugins/plugins/core/components/ChatTextEditor.js
  45. 38
      plugins/plugins/core/components/ChatWelcomePage.js
  46. 47
      plugins/plugins/core/components/ImageComponent.js
  47. 42
      plugins/plugins/core/components/LevelFounder.js
  48. 33
      plugins/plugins/core/components/NameMenu.js
  49. 6
      plugins/plugins/core/components/TimeAgo.js
  50. 158
      plugins/plugins/core/components/TipUser.js
  51. 1
      plugins/plugins/core/components/ToolTip.js
  52. 207
      plugins/plugins/core/components/UserInfo/UserInfo.js
  53. 51
      plugins/plugins/core/components/WrapperModal.js
  54. 214
      plugins/plugins/core/components/qdn-action-encryption.js
  55. 3
      plugins/plugins/core/components/qdn-action-types.js
  56. 1
      plugins/plugins/core/components/qortal-info-view.js
  57. 12
      plugins/plugins/core/group-management/group-management.src.js
  58. 22
      plugins/plugins/core/main.src.js
  59. 26
      plugins/plugins/core/messaging/chain-messaging/chain-messaging.src.js
  60. 17
      plugins/plugins/core/messaging/messaging.src.js
  61. 9654
      plugins/plugins/core/messaging/q-chat/q-chat.js
  62. 347
      plugins/plugins/core/messaging/q-chat/q-chat.src.js
  63. 13
      plugins/plugins/core/minting/minting-info.src.js
  64. 13
      plugins/plugins/core/name-registration/name-registration.src.js
  65. 12
      plugins/plugins/core/names-market/names-market.src.js
  66. 210
      plugins/plugins/core/node-management/node-management.src.js
  67. 2
      plugins/plugins/core/overview-page/overview-page-css.js
  68. 268
      plugins/plugins/core/overview-page/overview-page.src.js
  69. 15
      plugins/plugins/core/puzzles/puzzles.src.js
  70. 13
      plugins/plugins/core/q-app/q-apps.src.js
  71. 124
      plugins/plugins/core/qdn/browser/browser.src.js
  72. 13
      plugins/plugins/core/qdn/data-management/data-management.src.js
  73. 13
      plugins/plugins/core/qdn/publish/publish.src.js
  74. 13
      plugins/plugins/core/qdn/websites.src.js
  75. 18
      plugins/plugins/core/reward-share/reward-share.src.js
  76. 931
      plugins/plugins/core/sponsorship-list/sponsorship-list.src.js
  77. 123
      plugins/plugins/core/streams/onNewBlock.js
  78. 20
      plugins/plugins/core/streams/streams.js
  79. 13
      plugins/plugins/core/trade-bot/trade-bot-portal.src.js
  80. 25
      plugins/plugins/core/trade-portal/trade-portal.src.js
  81. 14
      plugins/plugins/core/wallet/wallet-app.src.js

4
README.md

@ -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.

3
core/language/de.json

@ -214,7 +214,8 @@
"wp1": "Prägung",
"wp2": "Nicht am Prägen",
"wp3": "Kerninformationen",
"wp4": "Synchronisiert"
"wp4": "Synchronisiert",
"wp5": "Synchronisierungsstatus"
},
"general": {
"yes": "Ja",

3
core/language/es.json

@ -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í",

3
core/language/fr.json

@ -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",

3
core/language/hindi.json

@ -215,7 +215,8 @@
"wp1": "खनन",
"wp2": "नट मििग",
"wp3": "मय जनक",
"wp4": "सिइजड"
"wp4": "सिइजड",
"wp5": "सिक सिि"
},
"general": {
"yes": "ह",

3
core/language/hr.json

@ -214,7 +214,8 @@
"wp1": "Kovanje",
"wp2": "Nije kovano",
"wp3": "Osnovne informacije",
"wp4": "Sinkronizirano"
"wp4": "Sinkronizirano",
"wp5": "Status sinkronizacije"
},
"general": {
"yes": "Da",

3
core/language/hu.json

@ -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",

3
core/language/it.json

@ -214,7 +214,8 @@
"wp1": "Conio",
"wp2": "Non conio",
"wp3": "Informazioni principali",
"wp4": "Sincronizzato"
"wp4": "Sincronizzato",
"wp5": "Stato sincronizzazione"
},
"general": {
"yes": "Yes",

3
core/language/jp.json

@ -216,7 +216,8 @@
"wp1": "ミント",
"wp2": "鋳造しない",
"wp3": "コア情報",
"wp4": "同期済み"
"wp4": "同期済み",
"wp5": "同期ステータス"
},
"general": {
"yes": "はい",

3
core/language/ko.json

@ -214,7 +214,8 @@
"wp1": "조폐",
"wp2": "조폐되지 않음",
"wp3": "핵심 정보",
"wp4": "동기화됨"
"wp4": "동기화됨",
"wp5": "동기화 상태"
},
"general": {
"yes": "예",

3
core/language/no.json

@ -214,7 +214,8 @@
"wp1": "Minting",
"wp2": "Ikke preging",
"wp3": "Kjerneinformasjon",
"wp4": "Synkronisert"
"wp4": "Synkronisert",
"wp5": "Synkroniseringsstatus"
},
"general": {
"yes": "Ja",

3
core/language/pl.json

@ -214,7 +214,8 @@
"wp1": "Bicie",
"wp2": "Nie bije",
"wp3": "Podstawowe informacje",
"wp4": "Zsynchronizowany"
"wp4": "Zsynchronizowany",
"wp5": "Stan synchronizacji"
},
"general": {
"yes": "Tak",

3
core/language/pt.json

@ -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",

3
core/language/ro.json

@ -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",

3
core/language/rs.json

@ -214,7 +214,8 @@
"wp1": "Kovanje",
"wp2": "Ne kuje",
"wp3": "Osnovne informacije",
"wp4": "Sinhronizovano"
"wp4": "Sinhronizovano",
"wp5": "Status sinhronizacije"
},
"general": {
"yes": "Da",

3
core/language/ru.json

@ -214,7 +214,8 @@
"wp1": "Чеканка",
"wp2": "Не чеканить",
"wp3": "Основная информация",
"wp4": "Синхронизировано"
"wp4": "Синхронизировано",
"wp5": "Статус синхронизации"
},
"general": {
"yes": "Да",

3
core/language/us.json

@ -219,7 +219,8 @@
"wp1": "Minting",
"wp2": "Not Minting",
"wp3": "Core Information",
"wp4": "Synchronized"
"wp4": "Synchronized",
"wp5": "Sync Status"
},
"general": {
"yes": "Yes",

3
core/language/zhc.json

@ -214,7 +214,8 @@
"wp1": "铸造",
"wp2": "不铸造",
"wp3": "核心信息",
"wp4": "已同步"
"wp4": "已同步",
"wp5": "同步状态"
},
"general": {
"yes": "是",

3
core/language/zht.json

@ -214,7 +214,8 @@
"wp1": "鑄造",
"wp2": "不鑄造",
"wp3": "核心信息",
"wp4": "已同步"
"wp4": "已同步",
"wp5": "同步狀態"
},
"general": {
"yes": "是",

29
core/src/components/app-view.js

@ -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"
}
}
clearTheCache() {
if (!isElectron()) {
} else {
targetDiv.style.display = "inline";
console.clear()
window.parent.electronAPI.clearMyCache()
window.parent.electronAPI.clearCache()
}
}

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"),

6
lib/preload.js

@ -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()
},
})

2654
package-lock.json generated

File diff suppressed because it is too large Load Diff

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"
}
}

12
plugins/plugins/core/become-minter/become-minter.src.js

@ -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) {

64
plugins/plugins/core/become-minter/components/not-sponsored.js

@ -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)

39
plugins/plugins/core/become-minter/components/yes-sponsored.js

@ -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)

4
plugins/plugins/core/components/ChatGifs/ChatGifs.js

@ -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)

18
plugins/plugins/core/components/ChatGifs/ChatGifsExplore.js

@ -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)

2
plugins/plugins/core/components/ChatGroupInvites.js

@ -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 })

18
plugins/plugins/core/components/ChatGroupSettings.js

@ -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 = {}

26
plugins/plugins/core/components/ChatGroupsManagement.js

@ -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 })

63
plugins/plugins/core/components/ChatHead.js

@ -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

17
plugins/plugins/core/components/ChatLeaveGroup.js

@ -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 {

2
plugins/plugins/core/components/ChatMessage.js

@ -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 })

60
plugins/plugins/core/components/ChatModals.js

@ -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)

1191
plugins/plugins/core/components/ChatPage.js

File diff suppressed because it is too large Load Diff

4
plugins/plugins/core/components/ChatRightPanel.js

@ -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() {

538
plugins/plugins/core/components/ChatScroller.js

@ -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

@ -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
plugins/plugins/core/components/ChatSelect.js

@ -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'

5
plugins/plugins/core/components/ChatSideNavHeads.js

@ -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) {

53
plugins/plugins/core/components/ChatTextEditor copy.js

@ -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';
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
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 })
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){

16
plugins/plugins/core/components/ChatTextEditor.js

@ -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;"
}

38
plugins/plugins/core/components/ChatWelcomePage.js

@ -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;

47
plugins/plugins/core/components/ImageComponent.js

@ -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)

42
plugins/plugins/core/components/LevelFounder.js

@ -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
}
}

33
plugins/plugins/core/components/NameMenu.js

@ -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()

6
plugins/plugins/core/components/TimeAgo.js

@ -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() {

158
plugins/plugins/core/components/TipUser.js

@ -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
plugins/plugins/core/components/ToolTip.js

@ -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 })

207
plugins/plugins/core/components/UserInfo/UserInfo.js

@ -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]
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
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;
}
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")}
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>
</div>
`
}
`
}
}
customElements.define('user-info', UserInfo);
customElements.define('user-info', UserInfo)

51
plugins/plugins/core/components/WrapperModal.js

@ -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)

214
plugins/plugins/core/components/qdn-action-encryption.js

@ -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")
}

3
plugins/plugins/core/components/qdn-action-types.js

@ -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
plugins/plugins/core/components/qortal-info-view.js

@ -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'

12
plugins/plugins/core/group-management/group-management.src.js

@ -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() {

22
plugins/plugins/core/main.src.js

@ -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)
}
});
});
})
})

26
plugins/plugins/core/messaging/chain-messaging/chain-messaging.src.js

@ -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') {

17
plugins/plugins/core/messaging/messaging.src.js

@ -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() {

9654
plugins/plugins/core/messaging/q-chat/q-chat.js

File diff suppressed because one or more lines are too long

347
plugins/plugins/core/messaging/q-chat/q-chat.src.js

@ -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 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/ChatSeachResults.js';
import snackbar from '../../components/snackbar.js'
import '@polymer/paper-spinner/paper-spinner-lite.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'
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 { Editor, Extension } from '@tiptap/core'
passiveSupport({ events: ['touchstart'] })
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' })
}

13
plugins/plugins/core/minting/minting-info.src.js

@ -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() {

13
plugins/plugins/core/name-registration/name-registration.src.js

@ -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() {

12
plugins/plugins/core/names-market/names-market.src.js

@ -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) {

210
plugins/plugins/core/node-management/node-management.src.js

@ -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)

2
plugins/plugins/core/overview-page/overview-page-css.js

@ -79,6 +79,8 @@ a:not([href]):not([tabindex]):focus {
img {
vertical-align: middle;
border-style: none;
height: 128px;
width: 128px;
}
caption {

268
plugins/plugins/core/overview-page/overview-page.src.js

@ -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)

15
plugins/plugins/core/puzzles/puzzles.src.js

@ -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() {

13
plugins/plugins/core/q-app/q-apps.src.js

@ -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() {

124
plugins/plugins/core/qdn/browser/browser.src.js

@ -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 = {};
data['error'] = errorMsg;
response = JSON.stringify(data);
break
}
const { encryptedData, publicKey } = data
if (!encryptedData) {
const errorMsg = `Missing fields: encryptedData`
data['error'] = errorMsg;
response = JSON.stringify(data);
break
try {
}
const uint8Array = base64ToUint8Array(encryptedData)
const combinedData = uint8Array
const str = "qortalEncryptedData";
const strEncoder = new TextEncoder();
const strUint8Array = strEncoder.encode(str);
const startsWithQortalEncryptedData = uint8ArrayStartsWith(uint8Array, "qortalEncryptedData");
if (startsWithQortalEncryptedData) {
if (!publicKey) {
const errorMsg = `Missing fields: publicKey`
data['error'] = errorMsg;
response = JSON.stringify(data);
break
}
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)
const decryptedDataToBase64 = decryptDeprecatedSingle(uint8Array, publicKey)
response = JSON.stringify(decryptedDataToBase64);
break;
if (!privateKey || !_publicKey) {
data['error'] = "Unable to retrieve keys"
response = JSON.stringify(data);
break
}
const startsWithQortalGroupEncryptedData = uint8ArrayStartsWith(uint8Array, "qortalGroupEncryptedData");
if (startsWithQortalGroupEncryptedData) {
const convertedPrivateKey = ed2curve.convertSecretKey(privateKey)
const convertedPublicKey = ed2curve.convertPublicKey(_publicKey)
const sharedSecret = new Uint8Array(32);
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey)
const decryptedData = decryptGroupData(encryptedData)
const decryptedDataToBase64 = uint8ArrayToBase64(decryptedData)
response = JSON.stringify(decryptedDataToBase64);
break;
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;
const errorMsg = "Unable to decrypt"
data['error'] = errorMsg;
response = JSON.stringify(data);
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() {

13
plugins/plugins/core/qdn/data-management/data-management.src.js

@ -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() {

13
plugins/plugins/core/qdn/publish/publish.src.js

@ -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() {

13
plugins/plugins/core/qdn/websites.src.js

@ -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() {

18
plugins/plugins/core/reward-share/reward-share.src.js

@ -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() {

931
plugins/plugins/core/sponsorship-list/sponsorship-list.src.js

File diff suppressed because it is too large Load Diff

123
plugins/plugins/core/streams/onNewBlock.js

@ -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)
}

20
plugins/plugins/core/streams/streams.js

@ -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 {

13
plugins/plugins/core/trade-bot/trade-bot-portal.src.js

@ -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() {

25
plugins/plugins/core/trade-portal/trade-portal.src.js

@ -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() {

14
plugins/plugins/core/wallet/wallet-app.src.js

@ -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…
Cancel
Save