Merge remote-tracking branch 'origin/master' into feature/group-encryption

This commit is contained in:
2023-07-22 16:21:16 +03:00
124 changed files with 25311 additions and 4681 deletions

View File

@@ -68,6 +68,10 @@ const generateForPlugins = () => {
in: 'plugins/core/main.src.js',
out: 'plugins/core/main.js',
},
{
in: 'plugins/core/overview-page/overview-page.src.js',
out: 'plugins/core/overview-page/overview-page.js',
},
{
in: 'plugins/core/trade-portal/trade-portal.src.js',
out: 'plugins/core/trade-portal/trade-portal.js',

View File

@@ -1,21 +1,23 @@
import { LitElement, html } from 'lit';
import { Epml } from '../../../epml.js';
import '../components/ButtonIconCopy.js';
import { use, translate, registerTranslateConfig } from 'lit-translate';
import { blocksNeed } from '../../utils/blocks-needed.js';
import { LitElement, html } from 'lit'
import { Epml } from '../../../epml.js'
import '../components/ButtonIconCopy.js'
import { use, translate, registerTranslateConfig } from 'lit-translate'
import { blocksNeed } from '../../utils/blocks-needed.js'
import isElectron from 'is-electron'
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 './components/not-sponsored.src';
import './components/yes-sponsored.src';
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
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 './components/not-sponsored.js'
import './components/yes-sponsored.js'
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
class BecomeMinter extends LitElement {
static get properties() {
@@ -27,77 +29,77 @@ class BecomeMinter extends LitElement {
addressInfo: { type: Object },
rewardSharePublicKey: { type: String },
mintingAccountData: { type: Array },
};
}
}
static styles = [pageStyles];
static styles = [pageStyles]
constructor() {
super();
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light';
this.sponsorshipKeyValue = '';
this.isPageLoading = true;
this.nodeInfo = {};
this.addressInfo = {};
this.rewardSharePublicKey = '';
this.mintingAccountData = null;
super()
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
this.sponsorshipKeyValue = ''
this.isPageLoading = true
this.nodeInfo = {}
this.addressInfo = {}
this.rewardSharePublicKey = ''
this.mintingAccountData = null
}
changeLanguage() {
const checkLanguage = localStorage.getItem('qortalLanguage');
const checkLanguage = localStorage.getItem('qortalLanguage')
if (checkLanguage === null || checkLanguage.length === 0) {
localStorage.setItem('qortalLanguage', 'us');
use('us');
localStorage.setItem('qortalLanguage', 'us')
use('us')
} else {
use(checkLanguage);
use(checkLanguage)
}
}
_handleStorage() {
const checkLanguage = localStorage.getItem('qortalLanguage');
const checkTheme = localStorage.getItem('qortalTheme');
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
use(checkLanguage);
use(checkLanguage)
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)
}
connectedCallback() {
super.connectedCallback();
window.addEventListener('storage', this._handleStorage);
super.connectedCallback()
window.addEventListener('storage', this._handleStorage)
}
disconnectedCallback() {
window.removeEventListener('storage', this._handleStorage);
super.disconnectedCallback();
window.removeEventListener('storage', this._handleStorage)
super.disconnectedCallback()
}
async getNodeInfo() {
const nodeInfo = await parentEpml.request('apiCall', {
url: `/admin/status`,
});
})
return nodeInfo;
return nodeInfo
}
async getMintingAcccounts() {
const mintingAccountData = await parentEpml.request('apiCall', {
url: `/admin/mintingaccounts`,
});
return mintingAccountData;
})
return mintingAccountData
}
async atMount() {
this.changeLanguage();
this.changeLanguage()
this.isPageLoading = true;
this.isPageLoading = true
try {
const [nodeInfo, myRewardShareArray, mintingaccounts] =
await Promise.all([
@@ -107,33 +109,40 @@ class BecomeMinter extends LitElement {
?.address
),
this.getMintingAcccounts(),
]);
])
this.nodeInfo = nodeInfo;
this.nodeInfo = nodeInfo
this.rewardSharePublicKey =
myRewardShareArray[0]?.rewardSharePublicKey;
this.isPageLoading = false;
this.mintingAccountData = mintingaccounts;
myRewardShareArray[0]?.rewardSharePublicKey
this.isPageLoading = false
this.mintingAccountData = mintingaccounts
this.addressInfo =
window.parent.reduxStore.getState().app.accountInfo.addressInfo;
window.parent.reduxStore.getState().app.accountInfo.addressInfo
} catch (error) {
console.error(error);
console.error(error)
this.isPageLoading = false;
this.isPageLoading = false
}
}
async firstUpdated() {
await this.atMount();
await this.atMount()
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
}
async getRewardShareRelationship(recipientAddress) {
const myRewardShareArray = await parentEpml.request('apiCall', {
type: 'api',
url: `/addresses/rewardshares?recipients=${recipientAddress}`,
});
})
return myRewardShareArray;
return myRewardShareArray
}
_levelUpBlocks() {
@@ -141,8 +150,8 @@ class BecomeMinter extends LitElement {
blocksNeed(0) -
(this.addressInfo?.blocksMinted +
this.addressInfo?.blocksMintedAdjustment)
).toString();
return countBlocksString;
).toString()
return countBlocksString
}
render() {
@@ -150,7 +159,7 @@ class BecomeMinter extends LitElement {
const findMintingAccount = this.mintingAccountData?.find(
(ma) => ma.recipientAccount === window.parent.reduxStore.getState().app?.selectedAddress
?.address
);
)
const isAlreadySponsored =
this.addressInfo?.error !== 124 &&
@@ -196,8 +205,8 @@ class BecomeMinter extends LitElement {
</yes-sponsored>
`}
</div>
`;
`
}
}
window.customElements.define('become-minter', BecomeMinter);
window.customElements.define('become-minter', BecomeMinter)

View File

@@ -6,8 +6,8 @@ import { use, 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 '@polymer/paper-spinner/paper-spinner-lite.js';
import '@material/mwc-button';
import '@material/mwc-textfield';
import '@vaadin/button';

File diff suppressed because it is too large Load Diff

View File

@@ -47,7 +47,7 @@ export const chatStyles = css`
.chat-list {
overflow-y: auto;
overflow-x: hidden;
height: 100%;
height: 96%;
box-sizing: border-box;
}

File diff suppressed because it is too large Load Diff

View File

@@ -478,31 +478,6 @@ class ChatWelcomePage extends LitElement {
getAddressPublicKey()
}
_textMenu(event) {
const getSelectedText = () => {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text;
}
return text;
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
_textArea(e) {
if (e.keyCode === 13 && !e.shiftKey) this._sendMessage()
}

View File

@@ -106,6 +106,7 @@ class LevelFounder extends LitElement {
}
firstUpdated() {
this.changeLanguage()
this.checkAddressInfo()
window.addEventListener('storage', () => {
@@ -167,28 +168,6 @@ class LevelFounder extends LitElement {
` : ''
}
_textMenu(event) {
const getSelectedText = () => {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text;
}
return text;
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
isEmptyArray(arr) {
if (!arr) { return true }
return arr.length === 0

File diff suppressed because it is too large Load Diff

View File

@@ -2,20 +2,29 @@ import nacl from '../../../../crypto/api/deps/nacl-fast.js'
import ed2curve from '../../../../crypto/api/deps/ed2curve.js'
let reader = new FileReader();
export const fileToBase64 = (file) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
if (!reader) {
reader = new FileReader();
}
reader.readAsDataURL(file);
reader.onload = () => {
const dataUrl = reader.result;
if (typeof dataUrl === "string") {
const base64String = dataUrl.split(',')[1];
reader.onload = null;
reader.onerror = null;
resolve(base64String);
} else {
reader.onload = null;
reader.onerror = null;
reject(new Error('Invalid data URL'));
}
};
reader.onerror = (error) => {
reader.onload = null;
reader.onerror = null;
reject(error);
};
});

View File

@@ -47,4 +47,7 @@ export const DECRYPT_DATA = 'DECRYPT_DATA'
export const DECRYPT_DATA_GROUP = 'DECRYPT_DATA_GROUP'
// SAVE_FILE
export const SAVE_FILE = 'SAVE_FILE'
export const SAVE_FILE = 'SAVE_FILE'
//SET_TAB_NOTIFICATIONS
export const SET_TAB_NOTIFICATIONS = 'SET_TAB_NOTIFICATIONS'

View File

@@ -1252,6 +1252,13 @@ class QortalInfoView extends LitElement {
`
}
firstUpdated() {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
openUserInfo(userData) {
if (userData.startsWith('Q') && userData.length == 34) {
this.getAddressUserResult(userData)

View File

@@ -1,6 +1,7 @@
import { LitElement, html, css } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../epml.js'
import isElectron from 'is-electron'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
registerTranslateConfig({
@@ -603,7 +604,7 @@ class GroupManagement extends LitElement {
</select>
</p>
<div style="margin-bottom: 10px;">
<p style="margin-bottom: 0;">${translate("walletpage.wchange21")} <span style="font-weight: bold;">${this.addGroupAdminFee} QORT<span></p>
<p style="margin-bottom: 0;">${translate("walletpage.wchange21")} <span style="font-weight: bold;">${this.createBanFee} QORT<span></p>
<br>
</div>
${this.renderClearSuccess()}
@@ -1499,6 +1500,9 @@ class GroupManagement extends LitElement {
</span>
<span ?hidden=${this.message === ''} style="${this.error ? 'color:red;' : ''}">
${this.message}
</span><br>
<span>
<b>${translate("walletpage.wchange21")} ${this.createFee} QORT.</b>
</span>
</div>
@@ -1556,6 +1560,9 @@ class GroupManagement extends LitElement {
</span>
<span ?hidden=${this.message === ''} style="${this.error ? 'color:red;' : ''}">
${this.message}
</span><br>
<span>
<b>${translate("walletpage.wchange21")} ${this.joinFee} QORT.</b>
</span>
</div>
@@ -1618,6 +1625,9 @@ class GroupManagement extends LitElement {
</span>
<span ?hidden=${this.message === ''} style="${this.error ? 'color:red;' : ''}">
${this.message}
</span><br>
<span>
<b>${translate("walletpage.wchange21")} ${this.leaveFee} QORT.</b>
</span>
</div>
@@ -1798,14 +1808,13 @@ class GroupManagement extends LitElement {
setTimeout(getOpen_JoinedGroups, 600000)
}
window.addEventListener("contextmenu", (event) => {
event.preventDefault();
this._textMenu(event)
})
window.addEventListener("click", () => {
parentEpml.request('closeCopyTextMenu', null)
})
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
@@ -1821,12 +1830,6 @@ class GroupManagement extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
}
let configLoaded = false
parentEpml.ready().then(() => {
@@ -1844,11 +1847,6 @@ class GroupManagement extends LitElement {
}
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
})
parentEpml.imReady()
}
@@ -2732,28 +2730,6 @@ class GroupManagement extends LitElement {
return html`<img src="${url}" onerror="this.src='/img/incognito.png';">`
}
_textMenu(event) {
const getSelectedText = () => {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text;
}
return text;
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
async createGroup(e) {
this.resetDefaultSettings()
const createFeeInput = this.createFee
@@ -3650,11 +3626,6 @@ class GroupManagement extends LitElement {
return apiKey
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
isEmptyArray(arr) {
if (!arr) { return true }
return arr.length === 0

File diff suppressed because one or more lines are too long

View File

@@ -7,12 +7,25 @@ let haveRegisteredNodeManagement = false;
parentEpml.ready().then(() => {
// pluginUrlsConf
let pluginUrlsConf = [
{
url: 'overview-page',
domain: 'core',
page: 'overview-page/index.html',
title: 'Overview Page',
icon: 'vaadin:info-circle',
mwcicon: 'home',
pluginNumber: 'plugin-OgcWeXBWBt',
menus: [],
parent: false,
},
{
url: 'minting',
domain: 'core',
page: 'minting/index.html',
title: 'Minting Details',
icon: 'vaadin:info-circle',
mwcicon: 'info_outline',
pluginNumber: 'plugin-iqKYTJzlcM',
menus: [],
parent: false,
},
@@ -21,7 +34,9 @@ parentEpml.ready().then(() => {
domain: 'core',
page: 'become-minter/index.html',
title: 'Become a Minter',
icon: 'vaadin:info-circle',
icon: 'vaadin:thumbs-up',
mwcicon: 'thumb_up',
pluginNumber: 'plugin-dVbRYnJNTs',
menus: [],
parent: false,
},
@@ -29,8 +44,10 @@ parentEpml.ready().then(() => {
url: 'sponsorship-list',
domain: 'core',
page: 'sponsorship-list/index.html',
title: 'Become a Minter',
icon: 'vaadin:info-circle',
title: 'Sponsorship List',
icon: 'vaadin:list-ol',
mwcicon: 'format_list_numbered',
pluginNumber: 'plugin-YxcLlHkgBl',
menus: [],
parent: false,
},
@@ -38,8 +55,10 @@ parentEpml.ready().then(() => {
url: 'wallet',
domain: 'core',
page: 'wallet/index.html',
title: 'Wallet',
title: 'Wallets',
icon: 'vaadin:wallet',
mwcicon: 'account_balance_wallet',
pluginNumber: 'plugin-kyhKaCIAZH',
menus: [],
parent: false,
},
@@ -49,6 +68,8 @@ parentEpml.ready().then(() => {
page: 'trade-portal/index.html',
title: 'Trade Portal',
icon: 'vaadin:bullets',
mwcicon: 'format_list_bulleted',
pluginNumber: 'plugin-zJoESuTpMG',
menus: [],
parent: false,
},
@@ -58,6 +79,8 @@ parentEpml.ready().then(() => {
page: 'trade-bot/index.html',
title: 'Auto Buy',
icon: 'vaadin:calc-book',
mwcicon: 'shop',
pluginNumber: 'plugin-mwPkCdVHsb',
menus: [],
parent: false,
},
@@ -67,51 +90,8 @@ parentEpml.ready().then(() => {
page: 'reward-share/index.html',
title: 'Reward Share',
icon: 'vaadin:share-square',
menus: [],
parent: false,
},
{
url: 'name-registration',
domain: 'core',
page: 'name-registration/index.html',
title: 'Name Registration',
icon: 'vaadin:user-check',
menus: [],
parent: false,
},
{
url: 'names-market',
domain: 'core',
page: 'names-market/index.html',
title: 'Names Market',
icon: 'vaadin:user-check',
menus: [],
parent: false,
},
{
url: 'websites',
domain: 'core',
page: 'qdn/index.html',
title: 'Websites',
icon: 'vaadin:desktop',
menus: [],
parent: false,
},
{
url: 'qapps',
domain: 'core',
page: 'q-app/index.html',
title: 'Q-Apps',
icon: 'vaadin:desktop',
menus: [],
parent: false,
},
{
url: 'data-management',
domain: 'core',
page: 'qdn/data-management/index.html',
title: 'Data Management',
icon: 'vaadin:database',
mwcicon: 'ios_share',
pluginNumber: 'plugin-PWZGtSxbPX',
menus: [],
parent: false,
},
@@ -121,6 +101,52 @@ parentEpml.ready().then(() => {
page: 'messaging/q-chat/index.html',
title: 'Q-Chat',
icon: 'vaadin:chat',
mwcicon: 'forum',
pluginNumber: 'plugin-qhsyOnpRhT',
menus: [],
parent: false,
},
{
url: 'name-registration',
domain: 'core',
page: 'name-registration/index.html',
title: 'Name Registration',
icon: 'vaadin:user-check',
mwcicon: 'manage_accounts',
pluginNumber: 'plugin-qCmtXAQmtu',
menus: [],
parent: false,
},
{
url: 'names-market',
domain: 'core',
page: 'names-market/index.html',
title: 'Names Market',
icon: 'vaadin:shop',
mwcicon: 'store',
pluginNumber: 'plugin-VVPhpHMnKM',
menus: [],
parent: false,
},
{
url: 'websites',
domain: 'core',
page: 'qdn/index.html',
title: 'Websites',
icon: 'vaadin:desktop',
mwcicon: 'desktop_mac',
pluginNumber: 'plugin-shITeUVkLG',
menus: [],
parent: false,
},
{
url: 'qapps',
domain: 'core',
page: 'q-app/index.html',
title: 'Q-Apps',
icon: 'vaadin:external-browser',
mwcicon: 'apps',
pluginNumber: 'plugin-MpiMASnQsT',
menus: [],
parent: false,
},
@@ -130,6 +156,19 @@ parentEpml.ready().then(() => {
page: 'group-management/index.html',
title: 'Group Management',
icon: 'vaadin:group',
mwcicon: 'group',
pluginNumber: 'plugin-fJZNpyLGTl',
menus: [],
parent: false,
},
{
url: 'data-management',
domain: 'core',
page: 'qdn/data-management/index.html',
title: 'Data Management',
icon: 'vaadin:database',
mwcicon: 'storage',
pluginNumber: 'plugin-QtaXNXHvRg',
menus: [],
parent: false,
},
@@ -139,6 +178,8 @@ parentEpml.ready().then(() => {
page: 'puzzles/index.html',
title: 'Puzzles',
icon: 'vaadin:puzzle-piece',
mwcicon: 'extension',
pluginNumber: 'plugin-wCGRmXRxht',
menus: [],
parent: false,
},
@@ -166,6 +207,8 @@ parentEpml.ready().then(() => {
page: 'node-management/index.html',
title: 'Node Management',
icon: 'vaadin:cloud',
mwcicon: 'cloud',
pluginNumber: 'plugin-TGAunWeWLU',
menus: [],
parent: false,
};

View File

@@ -1,4 +1,5 @@
import { LitElement, html, css } from 'lit'
import isElectron from 'is-electron'
class ChainMessaging extends LitElement {
static get properties() {
@@ -46,20 +47,16 @@ class ChainMessaging extends LitElement {
this.changeTheme()
setInterval(() => {
this.changeTheme();
}, 100)
setInterval(() => {
this.changeTheme();
}, 100)
window.addEventListener("contextmenu", (event) => {
event.preventDefault();
});
window.addEventListener("click", () => {
});
window.onkeyup = (e) => {
if (e.keyCode === 27) {
}
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
}

View File

@@ -1,5 +1,6 @@
import { LitElement, html, css } from 'lit'
import { Epml } from '../../../epml.js'
import isElectron from 'is-electron'
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
@@ -140,26 +141,16 @@ class Messaging extends LitElement {
this.changeTheme()
setInterval(() => {
this.changeTheme();
}, 100)
setInterval(() => {
this.changeTheme();
}, 100)
window.addEventListener("contextmenu", (event) => {
event.preventDefault();
this._textMenu(event)
});
window.addEventListener("click", () => {
parentEpml.request('closeCopyTextMenu', null)
});
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
let configLoaded = false
@@ -177,13 +168,6 @@ class Messaging extends LitElement {
}
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
})
parentEpml.imReady()
}
@@ -205,40 +189,6 @@ class Messaging extends LitElement {
onPageNavigation(pageUrl) {
parentEpml.request('setPageUrl', pageUrl)
}
_textMenu(event) {
const getSelectedText = () => {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text;
}
return text;
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
}
window.customElements.define('q-messaging', Messaging)

View File

@@ -9,6 +9,7 @@ import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } fro
import { qchatStyles } from './q-chat-css.src.js'
import WebWorker from 'web-worker:./computePowWorker.src.js';
import {repeat} from 'lit/directives/repeat.js';
import isElectron from 'is-electron'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
@@ -419,8 +420,6 @@ class Chat extends LitElement {
this.shadowRoot.getElementById('messageBox').addEventListener('keydown', stopKeyEventPropagation);
const runFunctionsAfterPageLoad = () => {
// Functions to exec after render while waiting for page info...
// getDataFromURL()
@@ -443,16 +442,6 @@ class Chat extends LitElement {
let runFunctionsAfterPageLoadInterval = setInterval(runFunctionsAfterPageLoad, 100);
window.addEventListener("contextmenu", (event) => {
event.preventDefault()
this._textMenu(event)
})
window.addEventListener("click", () => {
parentEpml.request('closeCopyTextMenu', null)
parentEpml.request('closeFramePasteMenu', null)
})
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
@@ -467,11 +456,12 @@ class Chat extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
parentEpml.request('closeFramePasteMenu', null)
}
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
let configLoaded = false
@@ -499,20 +489,11 @@ class Chat extends LitElement {
}).then(res => {
this.balance = res
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
})
parentEpml.imReady()
}
setOpenPrivateMessage(props) {
this.openPrivateMessage = props.open;
this.shadowRoot.getElementById("sendTo").value = props.name
@@ -549,8 +530,6 @@ class Chat extends LitElement {
window.location.href = `../../group-management/index.html`
}
async _sendMessage(outSideMsg, msg) {
this.isLoading = true;
@@ -914,44 +893,11 @@ class Chat extends LitElement {
}
}
_textMenu(event) {
const getSelectedText = () => {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text;
}
return text;
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
_textArea(e) {
if (e.keyCode === 13 && !e.shiftKey) this._sendMessage()
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
onPageNavigation(pageUrl) {
parentEpml.request('setPageUrl', pageUrl)
}

View File

@@ -1,6 +1,7 @@
import { LitElement, html, css } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../epml.js'
import isElectron from 'is-electron'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
registerTranslateConfig({
@@ -396,7 +397,15 @@ class MintingInfo extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
let configLoaded = false;
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
let configLoaded = false
parentEpml.ready().then(() => {
parentEpml.subscribe('selected_address', async selectedAddress => {
@@ -418,9 +427,6 @@ class MintingInfo extends LitElement {
}
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) this.clearSelection()
})
})
parentEpml.imReady()
}

View File

@@ -2,6 +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'
import isElectron from 'is-electron'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
@@ -562,15 +563,6 @@ class NameRegistration extends LitElement {
setTimeout(fetchMarketSellNames, 180000)
}
window.addEventListener("contextmenu", (event) => {
event.preventDefault()
this._textMenu(event)
})
window.addEventListener("click", () => {
parentEpml.request('closeCopyTextMenu', null)
})
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
@@ -585,10 +577,12 @@ class NameRegistration extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
let configLoaded = false
@@ -608,11 +602,6 @@ class NameRegistration extends LitElement {
}
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
})
parentEpml.imReady()
}
@@ -870,11 +859,6 @@ class NameRegistration extends LitElement {
return apiKey
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
async registerName(e) {
this.error = false
this.message = ''
@@ -1178,32 +1162,6 @@ class NameRegistration extends LitElement {
validateReceiver()
}
_textMenu(event) {
const getSelectedText = () => {
var text = ""
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString()
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text
}
return text
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
round(number) {
let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8)
return result

View File

@@ -2,7 +2,9 @@ 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 isElectron from 'is-electron'
import '../components/qortal-info-view.js'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
})
@@ -566,15 +568,6 @@ class NamesMarket extends LitElement {
setTimeout(fetchMarketSoldNames, 300000)
}
window.addEventListener("contextmenu", (event) => {
event.preventDefault()
this._textMenu(event)
})
window.addEventListener("click", () => {
parentEpml.request('closeCopyTextMenu', null)
})
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
@@ -589,10 +582,12 @@ class NamesMarket extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
let configLoaded = false
@@ -612,11 +607,6 @@ class NamesMarket extends LitElement {
}
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
})
parentEpml.imReady()
}
@@ -1026,11 +1016,6 @@ class NamesMarket extends LitElement {
return apiKey
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
async createCancelSellName() {
const name = this.shadowRoot.getElementById("toCancelSellName").value
const cancelSellFeeInput = this.cancelSellFee
@@ -1171,32 +1156,6 @@ class NamesMarket extends LitElement {
validateReceiver()
}
_textMenu(event) {
const getSelectedText = () => {
var text = ""
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString()
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text
}
return text
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
round(number) {
let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8)
return result

View File

@@ -1,6 +1,7 @@
import { LitElement, html, css } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../epml.js'
import isElectron from 'is-electron'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
registerTranslateConfig({
@@ -155,6 +156,7 @@ class NodeManagement extends LitElement {
<div class="node-card">
<h2>${translate("nodepage.nchange1")} ${this.nodeDomain}</h2>
<mwc-button style="float:right;" class="red" ?hidden="${(this.upTime === "offline")}" @click=${() => this.stopNode()}><mwc-icon>dangerous</mwc-icon>&nbsp;${translate("nodepage.nchange31")}</mwc-button>
<mwc-button style="float:right;" ?hidden="${(this.upTime === "offline")}" @click=${() => this.restartNode()}><mwc-icon>360</mwc-icon>&nbsp;${translate("nodepage.nchange33")}</mwc-button>
<span class="sblack"><br />${translate("nodepage.nchange2")} ${this.upTime}</span>
<br /><br />
<div id="minting">
@@ -283,22 +285,8 @@ class NodeManagement extends LitElement {
this.changeTheme()
this.changeLanguage()
// Call updateMintingAccounts
this.updateMintingAccounts()
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
this.isTextMenuOpen = true
this._textMenu(event)
})
window.addEventListener('click', () => {
if (this.isTextMenuOpen) {
parentEpml.request('closeCopyTextMenu', null)
}
})
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
@@ -313,37 +301,14 @@ class NodeManagement extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
this.shadowRoot.getElementById('addMintingAccountKey').addEventListener('contextmenu', (event) => {
const getSelectedText = () => {
var text = ''
if (typeof window.getSelection != 'undefined') {
text = window.getSelection().toString()
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
text = this.shadowRoot.selection.createRange().text
}
return text
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText()
if (selectedText && typeof selectedText === 'string') {
} else {
this.myElementId = ''
this.pasteMenu(event, 'addMintingAccountKey')
this.myElementId = this.shadowRoot.getElementById('addMintingAccountKey')
this.isPasteMenuOpen = true
event.preventDefault()
event.stopPropagation()
}
}
checkSelectedTextAndShowMenu()
})
// Calculate HH MM SS from Milliseconds...
const convertMsToTime = (milliseconds) => {
let day, hour, minute, seconds;
@@ -414,21 +379,6 @@ class NodeManagement extends LitElement {
}
this.config = JSON.parse(c);
})
parentEpml.subscribe('copy_menu_switch', async (value) => {
if (value === 'false' && this.isTextMenuOpen === true) {
this.clearSelection()
this.isTextMenuOpen = false
}
})
parentEpml.subscribe('frame_paste_menu_switch', async res => {
res = JSON.parse(res)
if (res.isOpen === false && this.isPasteMenuOpen === true) {
this.pasteToTextBox(this.myElementId)
this.isPasteMenuOpen = false
}
})
})
parentEpml.imReady()
}
@@ -501,6 +451,18 @@ class NodeManagement extends LitElement {
});
}
restartNode() {
parentEpml
.request("apiCall", {
url: `/admin/restart?apiKey=${this.getApiKey()}`,
method: "GET"
})
.then((res) => {
let err7string = get("nodepage.nchange34")
parentEpml.request('showSnackBar', `${err7string}`);
});
}
onPageNavigation(pageUrl) {
parentEpml.request("setPageUrl", pageUrl);
}
@@ -558,43 +520,6 @@ class NodeManagement extends LitElement {
});
}
pasteToTextBox(elementId) {
window.focus()
navigator.clipboard.readText().then((clipboardText) => {
elementId.value += clipboardText
elementId.focus()
})
}
pasteMenu(event, elementId) {
let eventObject = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY, elementId }
parentEpml.request('openFramePasteMenu', eventObject)
}
_textMenu(event) {
const getSelectedText = () => {
var text = ''
if (typeof window.getSelection != 'undefined') {
text = window.getSelection().toString()
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
text = this.shadowRoot.selection.createRange().text
}
return text
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText()
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
removeMintingAccount(publicKey) {
this.removeMintingAccountLoading = true;
@@ -622,11 +547,6 @@ class NodeManagement extends LitElement {
return apiKey;
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
isEmptyArray(arr) {
if (!arr) return true;
return arr.length === 0;

View File

@@ -0,0 +1,56 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/font/material-icons.css" />
<link rel="stylesheet" href="/font/switch-theme.css" />
<script>
const checkBack = localStorage.getItem('qortalTheme');
if (checkBack === 'dark') {
newtheme = 'dark';
} else {
newtheme = 'light';
}
document.querySelector('html').setAttribute('theme', newtheme);
</script>
<style>
html {
--scrollbarBG: #a1a1a1;
--thumbBG: #6a6c75;
}
*::-webkit-scrollbar {
width: 11px;
}
* {
scrollbar-width: thin;
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
}
*::-webkit-scrollbar-track {
background: var(--scrollbarBG);
}
*::-webkit-scrollbar-thumb {
background-color: var(--thumbBG);
border-radius: 6px;
border: 3px solid var(--scrollbarBG);
}
html,
body {
margin: 0;
font-family: 'Roboto', sans-serif;
background: var(--plugback);
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
}
</style>
</head>
<body>
<overview-page></overview-page>
<script src="overview-page.js"></script>
</body>
</html>

View File

@@ -0,0 +1,743 @@
import { css } from 'lit'
export const overviewStyle = css`
*,
*::before,
*::after {
box-sizing: border-box;
}
@-ms-viewport {
width: device-width;
}
figcaption,
footer,
main,
nav,
section {
display: block;
}
[tabindex='-1']:focus {
outline: 0 !important;
}
hr {
overflow: visible;
box-sizing: content-box;
height: 0;
}
h2,
h3,
h5 {
margin-top: 0;
margin-bottom: .5rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
dfn {
font-style: italic;
}
strong {
font-weight: bolder;
}
a {
text-decoration: none;
color: #5e72e4;
background-color: transparent;
-webkit-text-decoration-skip: objects;
}
a:hover {
text-decoration: none;
color: #233dd2;
}
a:not([href]):not([tabindex]) {
text-decoration: none;
color: inherit;
}
a:not([href]):not([tabindex]):hover,
a:not([href]):not([tabindex]):focus {
text-decoration: none;
color: inherit;
}
a:not([href]):not([tabindex]):focus {
outline: 0;
}
img {
vertical-align: middle;
border-style: none;
}
caption {
padding-top: 1rem;
padding-bottom: 1rem;
caption-side: bottom;
text-align: left;
color: #8898aa;
}
button {
border-radius: 0;
}
button:focus {
outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color;
}
input,
button {
font-family: inherit;
font-size: inherit;
line-height: inherit;
margin: 0;
}
button,
input {
overflow: visible;
}
button {
text-transform: none;
}
button,
[type='reset'],
[type='submit'] {
-webkit-appearance: button;
}
button::-moz-focus-inner,
[type='button']::-moz-focus-inner,
[type='reset']::-moz-focus-inner,
[type='submit']::-moz-focus-inner {
padding: 0;
border-style: none;
}
input[type='radio'],
input[type='checkbox'] {
box-sizing: border-box;
padding: 0;
}
input[type='date'],
input[type='time'],
input[type='datetime-local'],
input[type='month'] {
-webkit-appearance: listbox;
}
legend {
font-size: 1.5rem;
line-height: inherit;
display: block;
width: 100%;
max-width: 100%;
margin-bottom: .5rem;
padding: 0;
white-space: normal;
color: inherit;
}
[type='number']::-webkit-inner-spin-button,
[type='number']::-webkit-outer-spin-button {
height: auto;
}
[type='search'] {
outline-offset: -2px;
-webkit-appearance: none;
}
[type='search']::-webkit-search-cancel-button,
[type='search']::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
[hidden] {
display: none !important;
}
h2,
h3,
h4,
h5,
.h2,
.h3,
.h4,
.h5 {
font-family: inherit;
font-weight: 600;
line-height: 1.5;
margin-bottom: .5rem;
color: var(--black);
}
h2,
.h2 {
font-size: 1.25rem;
}
h3,
.h3 {
font-size: 1.0625rem;
}
h4,
.h4 {
font-size: 1.0625rem;
}
h5,
.h5 {
font-size: .8125rem;
}
hr {
margin-top: 2rem;
margin-bottom: 2rem;
border: 0;
border-top: 1px solid var(--app-hr);
}
.btn {
font-size: 1rem;
font-weight: 600;
line-height: 1.5;
display: inline-block;
padding: .625rem 1.25rem;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
text-align: center;
vertical-align: middle;
white-space: nowrap;
border: 1px solid transparent;
border-radius: .375rem;
cursor: none;
}
@media screen and (prefers-reduced-motion: reduce) {
.btn {
transition: none;
}
}
.btn:hover,
.btn:focus {
text-decoration: none;
cursor: none;
}
.btn:focus {
outline: 0;
box-shadow: 0 7px 14px rgba(50, 50, 93, .1), 0 3px 6px rgba(0, 0, 0, .08);
}
.btn:disabled {
opacity: .65;
box-shadow: none;
}
.opacity06 {
opacity: .6;
}
.btn:not(:disabled):not(.disabled) {
cursor: none;
}
.btn:not(:disabled):not(.disabled):active {
box-shadow: none;
}
.btn:not(:disabled):not(.disabled):active:focus {
box-shadow: 0 7px 14px rgba(50, 50, 93, .1), 0 3px 6px rgba(0, 0, 0, .08), none;
}
.btn-info {
color: #fff;
border-color: #03a9f4;
background-color: #03a9f4;
box-shadow: 0 4px 6px rgba(50, 50, 93, .11), 0 1px 3px rgba(0, 0, 0, .08);
}
.btn-info:hover {
color: #fff;
border-color: #03a9f4;
background-color: #03a9f4;
}
.btn-info:focus {
box-shadow: 0 4px 6px rgba(50, 50, 93, .11), 0 1px 3px rgba(0, 0, 0, .08), 0 0 0 0 rgba(17, 205, 239, .5);
}
.btn-info:disabled {
color: #fff;
border-color: #03a9f4;
background-color: #03a9f4;
}
.btn-info:not(:disabled):not(.disabled):active {
color: #fff;
border-color: #03a9f4;
background-color: #03a9f4;
}
.btn-info:not(:disabled):not(.disabled):active:focus {
box-shadow: none, 0 0 0 0 rgba(17, 205, 239, .5);
}
.btn-sm {
font-size: 2rem;
line-height: 1.5;
padding: .25rem .5rem;
border-radius: .375rem;
}
.card {
position: relative;
margin: auto;
display: flex;
flex-direction: column;
min-width: 0;
max-width: 60%;
word-wrap: break-word;
border-bottom-left-radius: 25px;
border-bottom-right-radius: 25px;
border: 1px solid var(--black);
background-color: var(--white);
}
.card>hr {
margin-right: 0;
margin-left: 0;
}
.card-body {
padding: 1rem;
flex: 1 1 auto;
}
.card-header {
margin-bottom: 0;
padding: 1.25rem 1.5rem;
border-left: 1px solid var(--black);
border-top: 1px solid var(--black);
border-right: 1px solid var(--black);
border-bottom: 1px solid rgba(0, 0, 0, .05);
background-color: var(--white);
}
@keyframes progress-bar-stripes {
from {
background-position: 1rem 0;
}
to {
background-position: 0 0;
}
}
.bg-default {
background-color: #172b4d !important;
}
a.bg-default:hover,
a.bg-default:focus,
button.bg-default:hover,
button.bg-default:focus {
background-color: #0b1526 !important;
}
.border-0 {
border: 0 !important;
}
.rounded-circle {
border-radius: 50% !important;
}
.d-flex {
display: flex !important;
}
.justify-content-center {
justify-content: center !important;
}
.justify-content-between {
justify-content: space-between !important;
}
.align-items-center {
align-items: center !important;
}
@media (min-width: 1200px) {
.justify-content-xl-between {
justify-content: space-between !important;
}
}
.float-right {
float: right !important;
}
.shadow,
.card-profile-image img {
box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .15) !important;
}
.mr-2 {
margin-right: .5rem !important;
}
.mt-4,
.my-4 {
margin-top: 1.5rem !important;
}
.mr-4 {
margin-right: 1.5rem !important;
}
.my-4 {
margin-bottom: 1.5rem !important;
}
.mb-5 {
margin-bottom: 3rem !important;
}
.mt-7 {
margin-top: 6rem !important;
}
.pt-0 {
padding-top: 0 !important;
}
.pb-0 {
padding-bottom: 0 !important;
}
.pt-8 {
padding-top: 8rem !important;
}
.m-auto {
margin: auto !important;
}
@media (min-width: 768px) {
.mt-md-5 {
margin-top: 3rem !important;
}
.mt-md-3 {
margin-top: 1.5rem !important;
}
.mt-md-1 {
margin-top: 0.5rem !important;
}
.pt-md-4 {
padding-top: 1rem !important;
}
.pb-md-4 {
padding-bottom: 1rem !important;
}
}
@media (min-width: 1200px) {
.mb-xl-0 {
margin-bottom: 0 !important;
}
}
.text-center {
text-align: center !important;
}
.font-weight-light {
font-weight: 300 !important;
}
@media print {
*,
*::before,
*::after {
box-shadow: none !important;
text-shadow: none !important;
}
a:not(.btn) {
text-decoration: underline;
}
img {
page-break-inside: avoid;
}
p,
h2,
h3 {
orphans: 3;
widows: 3;
}
h2,
h3 {
page-break-after: avoid;
}
@ page {
size: a3;
}
}
@keyframes floating-lg {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(15px);
}
100% {
transform: translateY(0px);
}
}
@keyframes floating {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(10px);
}
100% {
transform: translateY(0px);
}
}
@keyframes floating-sm {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(5px);
}
100% {
transform: translateY(0px);
}
}
[class*='shadow'] {
transition: all .15s ease;
}
.font-weight-300 {
font-weight: 300 !important;
}
.btn {
font-size: .875rem;
position: relative;
transition: all .15s ease;
letter-spacing: .025em;
text-transform: none;
will-change: transform;
}
.btn:hover {
cursor: none;
box-shadow: 0 7px 14px rgba(50, 50, 93, .1), 0 3px 6px rgba(0, 0, 0, .08);
}
.btn:not(:last-child) {
margin-right: .5rem;
}
.btn i:not(:first-child) {
margin-left: .5rem;
}
.btn i:not(:last-child) {
margin-right: .5rem;
}
.btn-sm {
font-size: 1rem;
}
[class*='btn-outline-'] {
border-width: 1px;
}
.card-profile-image {
position: relative;
}
.card-profile-image img {
position: absolute;
left: 50%;
max-width: 180px;
transition: all .15s ease;
transform: translate(-50%, -30%);
border-radius: .375rem;
}
.card-profile-stats {
padding: 0.5rem 0;
}
.card-profile-stats>div {
margin-right: 1rem;
padding: .875rem;
text-align: center;
}
.card-profile-stats>div:last-child {
margin-right: 0;
}
.card-profile-stats>div .heading {
font-size: 1rem;
font-weight: bold;
display: block;
color: var(--black);
}
.card-profile-stats>div .description {
font-size: 1rem;
color: #03a9f4;
}
.main-content {
position: relative;
}
.footer {
padding: 2.5rem 0;
background: #f7fafc;
}
.footer .copyright {
font-size: .875rem;
}
@media (min-width: 768px) {
@ keyframes show-navbar-dropdown {
0% {
transition: visibility .25s, opacity .25s, transform .25s;
transform: translate(0, 10px) perspective(200px) rotateX(-2deg);
opacity: 0;
}
100% {
transform: translate(0, 0);
opacity: 1;
}
}
@keyframes hide-navbar-dropdown {
from {
opacity: 1;
}
to {
transform: translate(0, 10px);
opacity: 0;
}
}
}
@keyframes show-navbar-collapse {
0% {
transform: scale(.95);
transform-origin: 100% 0;
opacity: 0;
}
100% {
transform: scale(1);
opacity: 1;
}
}
@keyframes hide-navbar-collapse {
from {
transform: scale(1);
transform-origin: 100% 0;
opacity: 1;
}
to {
transform: scale(.95);
opacity: 0;
}
}
p {
font-size: 1rem;
font-weight: 300;
line-height: 1.7;
color: var(--black);
}
.description {
font-size: 1rem;
}
.heading {
font-size: .95rem;
font-weight: 600;
letter-spacing: .025em;
text-transform: uppercase;
}
@media (max-width: 768px) {
.btn {
margin-bottom: 10px;
}
}
.red {
color: #C6011F;
}
`

View File

@@ -0,0 +1,794 @@
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 { overviewStyle } from './overview-page-css.js'
import { asyncReplace } from 'lit/directives/async-replace.js'
import "@material/mwc-button"
import '@material/mwc-dialog'
import '@vaadin/button';
import '@polymer/paper-spinner/paper-spinner-lite.js'
registerTranslateConfig({
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));
if (count === 0) {
callback()
}
}
}
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
class OverviewPage extends LitElement {
static get properties() {
return {
theme: { type: String, reflect: true },
nodeConfig: { type: Object },
accountInfo: { type: Object },
nodeInfo: { type: Array },
coreInfo: { type: Array },
imageUrl: { type: String },
myBalance: { type: Number }
}
}
static styles = [overviewStyle]
constructor() {
super()
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
this.nodeConfig = {}
this.accountInfo = {
names: [],
addressInfo: {}
}
this.nodeInfo = []
this.coreInfo = []
this.imageUrl = ''
this.myBalance = 0
}
render() {
return html`
<div class="main-content">
<div class="container mt-7">
<div class="row">
<div class="col-xl-8 m-auto order-xl-2 mb-5 mb-xl-0">
<div class="card card-profile shadow">
<div class="row justify-content-center">
<div class="col-lg-3 order-lg-2">
<div class="card-profile-image">
${this.getAvatar()}
</div>
</div>
</div>
<div class="card-header text-center border-0 pt-8 pt-md-4 pb-0 pb-md-4">
<div class="d-flex justify-content-between">
<span class="btn btn-sm btn-info mr-4">${translate("walletprofile.minterlevel")} ${this.accountInfo.addressInfo.level}</span>
${this.renderMintingStatus()}
</div>
</div>
<div class="card-body pt-0 pt-md-4">
<div class="text-center pt-0 mt-md-3">
<h2>${this.accountInfo.names.length !== 0 ? this.accountInfo.names[0].name : ''}</h2>
<div class="h3 font-weight-400">
${this.accountInfo.addressInfo.address}
</div>
<div class="h3 font-weight-400">
${translate("explorerpage.exp2")}: <span style="color: #03a9f4">${this.myBalance}</span> QORT
</div>
</div>
<div class="row">
<div class="col">
<div class="card-profile-stats d-flex justify-content-center">
<div>
<span class="heading">${this.accountInfo.addressInfo.blocksMinted + this.accountInfo.addressInfo.blocksMintedAdjustment}</span>
<span class="description">${translate("walletprofile.blocksminted")}</span>
</div>
</div>
</div>
</div>
<div class="text-center">
<hr class="my-4" style="color: var(--black)">
<h2>${translate("walletprofile.wp3")}</h2>
<div class="row">
<div class="col">
<div class="card-profile-stats d-flex justify-content-center">
<div>
<span class="heading">${this.coreInfo.buildVersion ? this.coreInfo.buildVersion : ''}</span>
<span class="description">${translate("appinfo.coreversion")}</span>
</div>
<div>
<span class="heading">${this.nodeInfo.height ? this.nodeInfo.height : ''}</span>
<span class="description">${translate("appinfo.blockheight")}</span>
</div>
<div>
<span class="heading">${this.nodeInfo.numberOfConnections ? this.nodeInfo.numberOfConnections : ''}</span>
<span class="description">${translate("appinfo.peers")}</span>
</div>
<div>
<span class="heading"><span class="${this.cssStatus2}">${this.renderSyncStatus()}</span></span>
<span class="description">${translate("walletpage.wchange41")}</span>
</div>
</div>
</div>
</div>
</div>
<div class="h5 float-right opacity06">
${translate("appinfo.uiversion")}: <span style="color: #03a9f4">${this.nodeConfig.version ? this.nodeConfig.version : ''}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`
}
firstUpdated() {
this.changeTheme()
this.changeLanguage()
this.nodeConfig = window.parent.reduxStore.getState().app.nodeConfig
this.accountInfo = window.parent.reduxStore.getState().app.accountInfo
this.getNodeInfo()
this.getCoreInfo()
this.getBalanceInfo()
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
use(checkLanguage)
if (checkTheme === 'dark') {
this.theme = 'dark'
} else {
this.theme = 'light'
}
document.querySelector('html').setAttribute('theme', this.theme)
})
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
setInterval(() => {
this.refreshItems()
}, 60000)
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === '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)
}
}
refreshItems() {
this.nodeConfig = window.parent.reduxStore.getState().app.nodeConfig
this.accountInfo = window.parent.reduxStore.getState().app.accountInfo
this.getNodeInfo()
this.getCoreInfo()
this.getBalanceInfo()
}
renderMintingStatus() {
if (this.nodeInfo.isMintingPossible === true && this.nodeInfo.isSynchronizing === true) {
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) {
this.cssStatus = ''
return html`<span class="btn btn-sm btn-info float-right">${translate("walletprofile.wp1")}</span>`
} else if (this.nodeInfo.isMintingPossible === false) {
return html`<span class="float-right"><start-minting-now></start-minting-now></span>`
}
}
renderSyncStatus() {
if (this.nodeInfo.isSynchronizing === true) {
this.cssStatus2 = 'red'
return html`${translate("appinfo.synchronizing")}... ${this.nodeInfo.syncPercent !== undefined ? this.nodeInfo.syncPercent + '%' : ''}`
} else if (this.nodeInfo.isSynchronizing === false) {
this.cssStatus2 = ''
return html`${translate("walletprofile.wp4")}`
}
}
getAvatar() {
if (this.accountInfo.names.length === 0) {
return html`<img class="rounded-circle" src="/img/incognito.png">`
} else {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const avatarUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
const url = `${avatarUrl}/arbitrary/THUMBNAIL/${this.accountInfo.names[0].name}/qortal_avatar?async=true}`
return html`<img class="rounded-circle" src="${url}" onerror="this.src='/img/incognito.png';" />`
}
}
async getNodeInfo() {
const infoNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const infoNodeUrl = infoNode.protocol + '://' + infoNode.domain + ':' + infoNode.port
const nodeUrl = `${infoNodeUrl}/admin/status`
await fetch(nodeUrl).then(response => {
return response.json()
})
.then(data => {
this.nodeInfo = data
})
.catch(err => {
console.error('Request failed', err)
})
}
async getCoreInfo() {
const infoCore = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const infoCoreUrl = infoCore.protocol + '://' + infoCore.domain + ':' + infoCore.port
const coreUrl = `${infoCoreUrl}/admin/info`
await fetch(coreUrl).then(response => {
return response.json()
})
.then(data => {
this.coreInfo = data
})
.catch(err => {
console.error('Request failed', err)
})
}
async getBalanceInfo() {
const infoBalance = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const infoBalanceUrl = infoBalance.protocol + '://' + infoBalance.domain + ':' + infoBalance.port
const balanceUrl = `${infoBalanceUrl}/addresses/balance/${this.accountInfo.addressInfo.address}`
await fetch(balanceUrl).then(response => {
return response.json()
})
.then(data => {
this.myBalance = data
})
.catch(err => {
console.error('Request failed', err)
})
}
}
window.customElements.define('overview-page', OverviewPage)
class StartMintingNow extends LitElement {
static get properties() {
return {
mintingAccountData: { type: Array },
errorMsg: { type: String },
openDialogRewardShare: { type: Boolean },
status: { type: Number },
timer: { type: Number },
privateRewardShareKey: { type: String }
};
}
static get styles() {
return [
css`
p, h1 {
color: var(--black)
}
.dialogCustom {
position: fixed;
z-index: 10000;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
top: 0px;
bottom: 0px;
left: 0px;
width: 100vw;
}
.dialogCustomInner {
width: 300px;
min-height: 400px;
background-color: var(--white);
box-shadow: var(--mdc-dialog-box-shadow, 0px 11px 15px -7px rgba(0, 0, 0, 0.2), 0px 24px 38px 3px rgba(0, 0, 0, 0.14), 0px 9px 46px 8px rgba(0, 0, 0, 0.12));
padding: 20px 24px;
border-radius: 4px;
}
.dialogCustomInner ul {
padding-left: 0px
}
.dialogCustomInner li {
margin-bottom: 10px;
}
.start-minting-wrapper {
z-index: 10;
}
.dialog-header h1 {
font-size: 18px;
}
.row {
display: flex;
width: 100%;
align-items: center;
}
.modalFooter {
width: 100%;
display: flex;
justify-content: flex-end;
}
.hide {
visibility: hidden
}
.inactiveText {
opacity: .60
}
.column {
display: flex;
flex-direction: column;
width: 100%;
}
.smallLoading,
.smallLoading:after {
border-radius: 50%;
width: 2px;
height: 2px;
}
.smallLoading {
border-width: 0.6em;
border-style: solid;
border-color: rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2)
rgba(3, 169, 244, 0.2) rgb(3, 169, 244);
font-size: 10px;
position: relative;
text-indent: -9999em;
transform: translateZ(0px);
animation: 1.1s linear 0s infinite normal none running loadingAnimation;
}
@-webkit-keyframes loadingAnimation {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes loadingAnimation {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.word-break {
word-break:break-all;
}
.dialog-container {
width: 300px;
min-height: 300px;
max-height: 75vh;
padding: 5px;
display: flex;
align-items: flex-start;
flex-direction: column;
}
.between {
justify-content: space-between;
}
.no-width {
width: auto
}
.between p {
margin: 0;
padding: 0;
color: var(--black);
}
.marginLoader {
margin-left: 10px;
}
.marginRight {
margin-right: 10px;
}
.warning{
display: flex;
flex-grow: 1
}
.message-error {
color: var(--error);
}
`,
];
}
constructor() {
super();
this.mintingAccountData = [];
this.errorMsg = '';
this.openDialogRewardShare = false;
this.status = 0;
this.privateRewardShareKey = "";
}
render() {
return html` ${this.renderStartMintingButton()} `;
}
firstUpdated() {
this.getMintingAcccounts();
}
renderErrorMsg1() {
return html`${translate("startminting.smchange1")}`
}
renderErrorMsg2() {
return html`${translate("startminting.smchange2")}`
}
renderErrorMsg3() {
return html`${translate("startminting.smchange3")}`
}
renderErrorMsg4() {
return html`${translate("startminting.smchange4")}`
}
async getMintingAcccounts() {
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 url = `${nodeUrl}/admin/mintingaccounts`
try {
const res = await fetch(url);
const mintingAccountData = await res.json()
this.mintingAccountData = mintingAccountData
} catch (error) {
this.errorMsg = this.renderErrorMsg1()
}
}
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
const address = window.parent.reduxStore.getState().app?.selectedAddress?.address
const findMintingAccountFromOtherUser = this.mintingAccountData.find((ma) => ma.recipientAccount === address && ma.mintingAccount !== address)
const removeMintingAccount = async (publicKey) => {
const url = `${nodeUrl}/admin/mintingaccounts?apiKey=${myNode.apiKey}`
return await fetch(url, {
method: 'DELETE',
body: publicKey,
})
}
const addMintingAccount = async (sponsorshipKeyValue) => {
const url = `${nodeUrl}/admin/mintingaccounts?apiKey=${myNode.apiKey}`
return await fetch(url, {
method: 'POST',
body: sponsorshipKeyValue,
})
}
try {
if (
findMintingAccountFromOtherUser &&
findMintingAccountFromOtherUser?.publicKey[0]
) {
await removeMintingAccount(
findMintingAccountFromOtherUser?.publicKey[0]
)
}
} catch (error) {
this.errorMsg = this.renderErrorMsg2()
return;
}
try {
await addMintingAccount(this.privateRewardShareKey)
let snack1 = get('becomeMinterPage.bchange19')
parentEpml.request('showSnackBar', `${snack1}`)
this.status = 5
this.getMintingAcccounts()
} catch (error) {
this.errorMsg = this.renderErrorMsg3()
return
}
}
async confirmRelationship() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
let interval = null
let stop = false
this.status = 2
const getAnswer = async () => {
const rewardShares = async (minterAddr) => {
const url = `${nodeUrl}/addresses/rewardshares?minters=${minterAddr}&recipients=${minterAddr}`
const res = await fetch(url)
const data = await res.json()
return data
}
if (!stop) {
stop = true;
try {
const address = window.parent.reduxStore.getState().app?.selectedAddress?.address
const myRewardShareArray = await rewardShares(address)
if (myRewardShareArray.length > 0) {
clearInterval(interval)
this.status = 3
this.timer = countDown(180, () => this.changeStatus(4))
}
} catch (error) {
}
stop = false
}
};
interval = setInterval(getAnswer, 5000)
}
renderStartMintingButton() {
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 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 findMintingAccount = mintingAccountData.find((ma) => ma.mintingAccount === address)
const isMinterButKeyMintingKeyNotAssigned = addressInfo?.error !== 124 && addressInfo?.level >= 1 && !findMintingAccount
const makeTransactionRequest = async (lastRef) => {
let mylastRef = lastRef;
let rewarddialog1 = get('transactions.rewarddialog1')
let rewarddialog2 = get('transactions.rewarddialog2')
let rewarddialog3 = get('transactions.rewarddialog3')
let rewarddialog4 = get('transactions.rewarddialog4')
let myTxnrequest = await parentEpml.request('transaction', {
type: 38,
nonce: nonce,
params: {
recipientPublicKey: publicAddress,
percentageShare: 0,
lastReference: mylastRef,
rewarddialog1: rewarddialog1,
rewarddialog2: rewarddialog2,
rewarddialog3: rewarddialog3,
rewarddialog4: rewarddialog4,
},
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'))) {
return err6string
}
if (txnResponse.success === false && txnResponse.message) {
throw (txnResponse);
} else if (
txnResponse.success === true &&
!txnResponse.data.error
) {
return err6string;
} else {
throw (txnResponse)
}
}
const createSponsorshipKey = async () => {
this.status = 1
let lastRef = await getLastRef()
let myTransaction = await makeTransactionRequest(lastRef)
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
}
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){
this.errorMsg = translate("startminting.smchange10")
return;
}
try {
this.privateRewardShareKey = await createSponsorshipKey()
this.confirmRelationship(publicAddress)
} catch (error) {
console.log({ error })
this.errorMsg = error?.data?.message || this.renderErrorMsg4()
return;
}
}
return html`
${isMinterButKeyMintingKeyNotAssigned ? html`
<div class="start-minting-wrapper">
<my-button label="${translate('becomeMinterPage.bchange18')}"
?isLoading=${false}
.onClick=${async () => {
await startMinting()
if (this.errorMsg) {
parentEpml.request('showSnackBar', `${this.errorMsg}`)
}
}}
>
</my-button>
</div>
<!-- Dialog for tracking the progress of starting minting -->
${this.openDialogRewardShare ? html`
<div class="dialogCustom">
<div class="dialogCustomInner">
<div class="dialog-header" >
<div class="row">
<h1>In progress</h1>
<div class=${`smallLoading marginLoader ${this.status > 3 && 'hide'}`}></div>
</div>
<hr />
</div>
<div class="dialog-container">
<ul>
<li class="row between">
<p>
1. ${translate("startminting.smchange5")}
</p>
<div class=${`smallLoading marginLoader ${this.status !== 1 && 'hide'}`}></div>
</li>
<li class=${`row between ${this.status < 2 && 'inactiveText'}`}>
<p>
2. ${translate("startminting.smchange6")}
</p>
<div class=${`smallLoading marginLoader ${this.status !== 2 && 'hide'}`}></div>
</li>
<li class=${`row between ${this.status < 3 && 'inactiveText'}`}>
<p>
3. ${translate("startminting.smchange7")}
</p>
<div class="row no-width">
<div class=${`smallLoading marginLoader marginRight ${this.status !== 3 && 'hide'}`} ></div> <p>${asyncReplace(this.timer)}</p>
</div>
</li>
<li class=${`row between ${this.status < 4 && 'inactiveText'}`}>
<p>
4. ${translate("startminting.smchange8")}
</p>
<div class=${`smallLoading marginLoader ${this.status !== 4 && 'hide'}`}></div>
</li>
<li class=${`row between ${this.status < 5 && 'inactiveText'}`}>
<p>
5. ${translate("startminting.smchange9")}
</p>
</li>
</ul>
<div class="warning column">
<p>
Warning: do not close the Qortal UI until completion!
</p>
<p class="message-error">${this.errorMsg}</p>
</div>
</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>
` : '' }
</div>
</div>
</div>
` : ""}
` : ''}
`;
}
}
window.customElements.define('start-minting-now', StartMintingNow)
class MyButton extends LitElement {
static properties = {
onClick: { type: Function },
isLoading: { type: Boolean },
label: { type: String },
};
static styles = css`
vaadin-button {
font-size: 1rem;
font-weight: 600;
height: 35px;
margin: 0;
cursor: pointer;
min-width: 80px;
min-height: 35px;
background-color: #03a9f4;
color: white;
}
vaadin-button:hover {
opacity: 0.9;
}
`;
constructor() {
super();
this.onClick = () => {};
this.isLoading = false;
this.label = '';
}
render() {
return html`
<vaadin-button
?disabled="${this.isLoading}"
@click="${this.onClick}"
>
${this.isLoading === false
? html`${this.label}`
: html`<paper-spinner-lite active></paper-spinner-lite>`}
</vaadin-button>
`;
}
}
customElements.define('my-button', MyButton)

View File

@@ -1,13 +1,13 @@
import { LitElement, html, css } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../epml.js'
import isElectron from 'is-electron'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
})
// Not sure if these are imported in the proper way:
import nacl from '../../../../crypto/api/deps/nacl-fast.js'
import Base58 from '../../../../crypto/api/deps/Base58.js'
import publicKeyToAddress from '../../../../crypto/api/wallet/publicKeyToAddress.js'
@@ -184,15 +184,6 @@ class Puzzles extends LitElement {
this.changeTheme()
this.changeLanguage()
window.addEventListener("contextmenu", (event) => {
event.preventDefault();
this._textMenu(event)
})
window.addEventListener("click", () => {
parentEpml.request('closeCopyTextMenu', null)
})
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
@@ -207,10 +198,12 @@ class Puzzles extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
const textBox = this.shadowRoot.getElementById("puzzleGuess")
@@ -335,55 +328,8 @@ class Puzzles extends LitElement {
}
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
parentEpml.subscribe('frame_paste_menu_switch', async res => {
res = JSON.parse(res)
if (res.isOpen === false && this.isPasteMenuOpen === true) {
this.pasteToTextBox(textBox)
this.isPasteMenuOpen = false
}
})
})
parentEpml.imReady()
textBox.addEventListener('contextmenu', (event) => {
const getSelectedText = () => {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text;
}
return text;
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
// ...
} else {
this.pasteMenu(event)
this.isPasteMenuOpen = true
// Prevent Default and Stop Event Bubbling
event.preventDefault()
event.stopPropagation()
}
}
checkSelectedTextAndShowMenu()
})
}
changeTheme() {
@@ -486,54 +432,10 @@ class Puzzles extends LitElement {
this.loading = false
}
pasteToTextBox(textBox) {
// Return focus to the window
window.focus()
navigator.clipboard.readText().then(clipboardText => {
textBox.value += clipboardText
textBox.focus()
});
}
pasteMenu(event) {
let eventObject = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
parentEpml.request('openFramePasteMenu', eventObject)
}
_textMenu(event) {
const getSelectedText = () => {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text;
}
return text;
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
isEmptyArray(arr) {
if (!arr) { return true }
return arr.length === 0
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
}
window.customElements.define('puzzles-info', Puzzles)

View File

@@ -3,11 +3,13 @@ import { render } from 'lit/html.js'
import { Epml } from '../../../epml.js'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
import { columnBodyRenderer, gridRowDetailsRenderer } from '@vaadin/grid/lit.js'
import isElectron from 'is-electron'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
})
import '@material/mwc-dialog'
import '@material/mwc-icon'
import '@material/mwc-button'
import '@material/mwc-tab-bar'
@@ -49,7 +51,16 @@ class QApps extends LitElement {
* {
--mdc-theme-primary: rgb(3, 169, 244);
--mdc-button-disabled-fill-color: rgba(3, 169, 244, 0.5);
--mdc-theme-surface: var(--white);
--mdc-text-field-outlined-idle-border-color: var(--txtfieldborder);
--mdc-text-field-outlined-hover-border-color: var(--txtfieldhoverborder);
--mdc-text-field-label-ink-color: var(--black);
--mdc-text-field-ink-color: var(--black);
--mdc-dialog-content-ink-color: var(--black);
--mdc-dialog-shape-radius: 25px;
--mdc-dialog-min-width: 300px;
--mdc-dialog-max-width: auto;
--mdc-dialog-max-height: 700px;
--paper-input-container-focus-color: var(--mdc-theme-primary);
--lumo-primary-text-color: rgb(0, 167, 245);
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
@@ -379,49 +390,10 @@ class QApps extends LitElement {
<div id="tabs-1-content">
<div id="tab-browse-content">
<div style="min-height:48px; display: flex; padding-bottom: 6px; margin: 2px;">
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${translate("appspage.schange1")}</h2>
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
<h2 style="margin: 0; padding-top: .5em; display: inline;">${translate("appspage.schange1")}</h2>
<h2 style="margin: 0; flex: 6; padding-top: .5em; display: inline;">${this.renderSearchButton()}</h2>
<h2 style="margin: 0; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
</div>
<div class="divCard">
<h3 style="margin: 0; margin-bottom: 1em; text-align: left;">${translate("appspage.schange4")}</h3>
<div id="search">
<vaadin-text-field theme="medium" id="searchName" placeholder="${translate("appspage.schange33")}" value="${this.searchName}" @keydown="${this.searchListener}" clear-button-visible>
<vaadin-icon slot="prefix" icon="vaadin:user"></vaadin-icon>
</vaadin-text-field>&nbsp;&nbsp;<br>
<vaadin-button theme="medium" @click="${(e) => this.doSearch(e)}">
<vaadin-icon icon="vaadin:search" slot="prefix"></vaadin-icon>
${translate("appspage.schange35")}
</vaadin-button>
</div><br />
<vaadin-grid theme="wrap-cell-content" id="searchResourcesGrid" ?hidden="${this.isEmptyArray(this.searchResources)}" .items="${this.searchResources}" aria-label="Search apps" all-rows-visible>
<vaadin-grid-column width="7rem" flex-grow="0" header="${translate("appspage.schange5")}" .renderer=${(root, column, data) => {
render(html`${this.renderAvatar(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column header="${translate("appspage.schange6")}" .renderer=${(root, column, data) => {
render(html`${this.renderInfo(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="12rem" flex-grow="0" header="${translate("appspage.schange7")}" .renderer=${(root, column, data) => {
render(html`${this.renderPublishedBy(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="14rem" flex-grow="0" header="" .renderer=${(root, column, data) => {
render(html`${this.renderDownload(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="10rem" flex-grow="0" header="${translate("appspage.schange8")}" .renderer=${(root, column, data) => {
render(html`${this.renderFollowUnfollowButton(data.item)}`, root);
}}>
</vaadin-grid-column>
<vaadin-grid-column width="10rem" flex-grow="0" header="" .renderer=${(root, column, data) => {
render(html`${this.renderBlockUnblockButton(data.item)}`, root);
}}>
</vaadin-grid-column>
</vaadin-grid><br />
</div>
<div class="divCard">
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">${translate("appspage.schange9")}</h3>
<vaadin-grid theme="wrap-cell-content" id="resourcesGrid" ?hidden="${this.isEmptyArray(this.pageRes)}" .items="${this.pageRes}" aria-label="apps" all-rows-visible>
<vaadin-grid-column width="7rem" flex-grow="0" header="${translate("appspage.schange5")}" .renderer=${(root, column, data) => {
render(html`${this.renderAvatar(data.item)}`, root)
@@ -455,15 +427,14 @@ class QApps extends LitElement {
${this.isEmptyArray(this.pageRes) ? html`
<span style="color: var(--black);">${translate("appspage.schange10")}</span>
` : ''}
</div>
${this.renderRelayModeText()}<br>
</div>
<div id="tab-followed-content">
<div style="min-height:48px; display: flex; padding-bottom: 6px; margin: 2px;">
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${translate("appspage.schange11")}</h2>
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
<h2 style="margin: 0; padding-top: .5em; display: inline;">${translate("appspage.schange11")}</h2>
<h2 style="margin: 0; flex: 6; padding-top: .5em; display: inline;">${this.renderSearchButton()}</h2>
<h2 style="margin: 0; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
</div>
<div class="divCard">
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">${translate("appspage.schange12")}</h3>
<vaadin-grid theme="wrap-cell-content" id="followedResourcesGrid" ?hidden="${this.isEmptyArray(this.followedResources)}" .items="${this.followedResources}" aria-label="Followed apps" all-rows-visible>
<vaadin-grid-column width="7rem" flex-grow="0" header="${translate("appspage.schange5")}" .renderer=${(root, column, data) => {
@@ -478,16 +449,12 @@ class QApps extends LitElement {
render(html`${this.renderPublishedBy(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="14rem" flex-grow="0" header="" .renderer=${(root, column, data) => {
<vaadin-grid-column width="14rem" flex-grow="0" header="${translate("appspage.schange8")}" .renderer=${(root, column, data) => {
render(html`${this.renderDownload(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="10rem" flex-grow="0" header="${translate("appspage.schange8")}" .renderer=${(root, column, data) => {
render(html`${this.renderFollowUnfollowButton(data.item)}`, root);
}}>
</vaadin-grid-column>
<vaadin-grid-column width="10rem" flex-grow="0" header="" .renderer=${(root, column, data) => {
render(html`${this.renderBlockUnblockButton(data.item)}`, root);
render(html`${this.renderFollowUnfollowButtonTab(data.item)}`, root);
}}>
</vaadin-grid-column>
</vaadin-grid>
@@ -497,15 +464,14 @@ class QApps extends LitElement {
${this.isEmptyArray(this.followedResources) ? html`
<span style="color: var(--black);">${translate("appspage.schange13")}</span>
` : ''}
</div>
${this.renderRelayModeText()}
</div>
<div id="tab-blocked-content">
<div style="min-height:48px; display: flex; padding-bottom: 6px; margin: 2px;">
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${translate("appspage.schange14")}</h2>
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
<h2 style="margin: 0; padding-top: .5em; display: inline;">${translate("appspage.schange14")}</h2>
<h2 style="margin: 0; flex: 6; padding-top: .5em; display: inline;">${this.renderSearchButton()}</h2>
<h2 style="margin: 0; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
</div>
<div class="divCard">
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">${translate("appspage.schange15")}</h3>
<vaadin-grid theme="wrap-cell-content" id="blockedResourcesGrid" ?hidden="${this.isEmptyArray(this.blockedResources)}" .items="${this.blockedResources}" aria-label="Blocked apps" all-rows-visible>
<vaadin-grid-column width="7rem" flex-grow="0" header="${translate("appspage.schange5")}" .renderer=${(root, column, data) => {
@@ -520,16 +486,8 @@ class QApps extends LitElement {
render(html`${this.renderPublishedBy(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="14rem" flex-grow="0" header="" .renderer=${(root, column, data) => {
render(html`${this.renderDownload(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="10rem" flex-grow="0" header="${translate("appspage.schange8")}" .renderer=${(root, column, data) => {
render(html`${this.renderFollowUnfollowButton(data.item)}`, root);
}}>
</vaadin-grid-column>
<vaadin-grid-column width="10rem" flex-grow="0" header="" .renderer=${(root, column, data) => {
render(html`${this.renderBlockUnblockButton(data.item)}`, root);
render(html`${this.renderBlockUnblockButtonTab(data.item)}`, root);
}}>
</vaadin-grid-column>
</vaadin-grid>
@@ -539,12 +497,44 @@ class QApps extends LitElement {
${this.isEmptyArray(this.blockedResources) ? html`
<span style="color: var(--black);">${translate("appspage.schange16")}</span>
` : ''}
</div>
${this.renderRelayModeText()}
</div>
</div>
</div>
<mwc-dialog id="searchAppDialog">
<h3 style="margin: 0; margin-bottom: 1em; text-align: left;">${translate("appspage.schange4")}</h3>
<div id="search">
<vaadin-text-field theme="medium" id="searchName" placeholder="${translate("appspage.schange33")}" value="${this.searchName}" @keydown="${this.searchListener}" clear-button-visible>
<vaadin-icon slot="prefix" icon="vaadin:user"></vaadin-icon>
</vaadin-text-field>&nbsp;&nbsp;<br>
<vaadin-button theme="medium" @click="${(e) => this.doSearch(e)}">
<vaadin-icon icon="vaadin:search" slot="prefix"></vaadin-icon>
${translate("appspage.schange35")}
</vaadin-button>
</div><br />
<vaadin-grid theme="wrap-cell-content" id="searchResourcesGrid" ?hidden="${this.isEmptyArray(this.searchResources)}" .items="${this.searchResources}" aria-label="Search apps" all-rows-visible>
<vaadin-grid-column width="7rem" flex-grow="0" header="${translate("appspage.schange5")}" .renderer=${(root, column, data) => {
render(html`${this.renderAvatar(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="12rem" flex-grow="0" header="${translate("appspage.schange7")}" .renderer=${(root, column, data) => {
render(html`${this.renderPublishedBy(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="14rem" flex-grow="0" header="" .renderer=${(root, column, data) => {
render(html`${this.renderDownload(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="10rem" flex-grow="0" header="${translate("appspage.schange8")}" .renderer=${(root, column, data) => {
render(html`${this.renderFollowUnfollowButton(data.item)}`, root);
}}>
</vaadin-grid-column>
<vaadin-grid-column width="10rem" flex-grow="0" header="" .renderer=${(root, column, data) => {
render(html`${this.renderBlockUnblockButton(data.item)}`, root);
}}>
</vaadin-grid-column>
</vaadin-grid>
</mwc-dialog>
<paper-dialog id="downloadProgressDialog" class="progress" modal>
<div class="lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
<h2>${translate("appspage.schange41")}</h2>
@@ -589,21 +579,6 @@ class QApps extends LitElement {
setTimeout(getRelayMode, 600000)
}
window.addEventListener("contextmenu", (event) => {
event.preventDefault();
this._textMenu(event)
});
window.addEventListener("click", () => {
parentEpml.request('closeCopyTextMenu', null)
});
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
}
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
@@ -618,6 +593,14 @@ class QApps extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
let configLoaded = false
parentEpml.ready().then(() => {
@@ -639,11 +622,6 @@ class QApps extends LitElement {
}
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
})
parentEpml.imReady()
}
@@ -677,9 +655,25 @@ class QApps extends LitElement {
const tabBrowseContent = this.shadowRoot.getElementById('tab-browse-content')
const tabFollowedContent = this.shadowRoot.getElementById('tab-followed-content')
const tabBlockedContent = this.shadowRoot.getElementById('tab-blocked-content')
tabBrowseContent.style.display = (tab === 'browse') ? 'block' : 'none'
tabFollowedContent.style.display = (tab === 'followed') ? 'block' : 'none'
tabBlockedContent.style.display = (tab === 'blocked') ? 'block' : 'none'
if (tab === 'browse') {
this.refreshapps()
tabBrowseContent.style.display = 'block'
tabFollowedContent.style.display = 'none'
tabBlockedContent.style.display = 'none'
} else if (tab === 'followed') {
this.getFollowedNamesRefresh()
this.getFollowedNamesResource()
tabBrowseContent.style.display = 'none'
tabFollowedContent.style.display = 'block'
tabBlockedContent.style.display = 'none'
} else if (tab === 'blocked') {
this.getBlockedNamesRefresh()
this.getBlockedNamesResource()
tabBrowseContent.style.display = 'none'
tabFollowedContent.style.display = 'none'
tabBlockedContent.style.display = 'block'
} else {
}
}
searchListener(e) {
@@ -884,6 +878,16 @@ class QApps extends LitElement {
return html`<mwc-button style="float:right;" @click=${() => this.publishApp()}><mwc-icon>add</mwc-icon>${translate("appspage.schange21")}</mwc-button>`
}
renderSearchButton() {
return html`<mwc-button style="float:right;" @click=${() => this.openSearchDialog()}><mwc-icon>search</mwc-icon>${translate("appspage.schange4")}</mwc-button>`
}
openSearchDialog() {
this.searchResources = []
this.shadowRoot.getElementById('searchName').value = ''
this.shadowRoot.getElementById('searchAppDialog').show()
}
renderDownload(downObj) {
if (downObj.status.description === "Published but not yet downloaded" || downObj.status.status === "MISSING_DATA") {
return html`<mwc-button ?disabled="${this.btnDisabled}" dense unelevated label="${translate("appspage.schange36")}" icon="download" @click=${() => this.downloadApp(downObj)}></mwc-button>`
@@ -947,6 +951,8 @@ class QApps extends LitElement {
this.textProgress = ''
this.shadowRoot.getElementById('downloadProgressDialog').close()
this.getData(0)
this.getFollowedNamesRefresh()
this.getFollowedNamesResource()
this.updateComplete.then(() => this.requestUpdate())
} else if (status.id === "BUILDING") {
this.btnDisabled = true
@@ -1014,8 +1020,6 @@ class QApps extends LitElement {
this.followedNames.push(name)
this.getFollowedNamesRefresh()
this.getFollowedNamesResource()
this.refreshapps()
this.updateComplete.then(() => this.requestUpdate())
} else {
let err3string = get("appspage.schange22")
parentEpml.request('showSnackBar', `${err3string}`)
@@ -1041,10 +1045,6 @@ class QApps extends LitElement {
if (ret === true) {
this.followedNames = this.followedNames.filter(item => item != name)
this.getFollowedNamesRefresh()
this.getFollowedNamesResource()
this.refreshapps()
this.updateComplete.then(() => this.requestUpdate())
} else {
let err4string = get("appspage.schange23")
parentEpml.request('showSnackBar', `${err4string}`)
@@ -1052,6 +1052,33 @@ class QApps extends LitElement {
return ret
}
async unfollowNameTab(appObj) {
let name = appObj.name
let items = [
name
]
let namesJsonString = JSON.stringify({ "items": items })
let ret = await parentEpml.request('apiCall', {
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
body: `${namesJsonString}`
})
if (ret === true) {
this.followedNames = this.followedNames.filter(item => item != name)
this.getFollowedNamesRefresh()
this.getFollowedNamesResource()
} else {
let err4string = get("websitespage.schange23")
parentEpml.request('showSnackBar', `${err4string}`)
}
return ret
}
async blockName(appObj) {
let name = appObj.name
let items = [
@@ -1071,10 +1098,6 @@ class QApps extends LitElement {
if (ret === true) {
this.blockedNames = this.blockedNames.filter(item => item != name)
this.blockedNames.push(name)
this.getBlockedNamesRefresh()
this.getBlockedNamesResource()
this.refreshapps()
this.updateComplete.then(() => this.requestUpdate())
} else {
let err5string = get("appspage.schange24")
parentEpml.request('showSnackBar', `${err5string}`)
@@ -1100,10 +1123,6 @@ class QApps extends LitElement {
if (ret === true) {
this.blockedNames = this.blockedNames.filter(item => item != name)
this.getBlockedNamesRefresh()
this.getBlockedNamesResource()
this.refreshapps()
this.updateComplete.then(() => this.requestUpdate())
} else {
let err6string = get("appspage.schange25")
parentEpml.request('showSnackBar', `${err6string}`)
@@ -1111,6 +1130,33 @@ class QApps extends LitElement {
return ret
}
async unblockNameTab(appObj) {
let name = appObj.name
let items = [
name
]
let namesJsonString = JSON.stringify({ "items": items })
let ret = await parentEpml.request('apiCall', {
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`,
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
body: `${namesJsonString}`
})
if (ret === true) {
this.blockedNames = this.blockedNames.filter(item => item != name)
this.getBlockedNamesRefresh()
this.getBlockedNamesResource()
} else {
let err6string = get("websitespage.schange25")
parentEpml.request('showSnackBar', `${err6string}`)
}
return ret
}
renderInfo(appObj) {
let name = appObj.name
let title = name
@@ -1176,6 +1222,21 @@ class QApps extends LitElement {
}
}
renderFollowUnfollowButtonTab(appObj) {
let name = appObj.name
if (this.followedNames == null || !Array.isArray(this.followedNames)) {
return html``
}
if (this.followedNames.indexOf(name) === -1) {
return html`<mwc-button @click=${() => this.followNameTab(appObj)}><mwc-icon>add_to_queue</mwc-icon>&nbsp;${translate("appspage.schange29")}</mwc-button>`
}
else {
return html`<mwc-button @click=${() => this.unfollowNameTab(appObj)}><mwc-icon>remove_from_queue</mwc-icon>&nbsp;${translate("appspage.schange30")}</mwc-button>`
}
}
renderBlockUnblockButton(appObj) {
let name = appObj.name
@@ -1190,6 +1251,24 @@ class QApps extends LitElement {
}
}
renderBlockUnblockButtonTab(appObj) {
let name = appObj.name
// Only show the block/unblock button if we have permission to modify the list on this node
if (this.blockedNames == null || !Array.isArray(this.blockedNames)) {
return html``
}
if (this.blockedNames.indexOf(name) === -1) {
// render block button
return html`<mwc-button @click=${() => this.blockNameTab(appObj)}><mwc-icon>block</mwc-icon>&nbsp;${translate("appspage.schange31")}</mwc-button>`
}
else {
// render unblock button
return html`<mwc-button @click=${() => this.unblockNameTab(appObj)}><mwc-icon>radio_button_unchecked</mwc-icon>&nbsp;${translate("appspage.schange32")}</mwc-button>`
}
}
bytesToSize(bytes) {
var sizes = ['bytes', 'KB', 'MB', 'GB', 'TB']
if (bytes == 0) return '0 bytes'
@@ -1197,39 +1276,12 @@ class QApps extends LitElement {
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i]
}
_textMenu(event) {
const getSelectedText = () => {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text;
}
return text
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
getApiKey() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let apiKey = myNode.apiKey
return apiKey
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
isEmptyArray(arr) {
if (!arr) { return true }
return arr.length === 0

View File

@@ -1,30 +1,27 @@
import { LitElement, html, css } from 'lit';
import { render } from 'lit/html.js';
import { Epml } from '../../../../epml';
import {
use,
get,
translate,
translateUnsafeHTML,
registerTranslateConfig,
} from 'lit-translate';
import { LitElement, html, css } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../../epml'
import isElectron from 'is-electron'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
registerTranslateConfig({
loader: (lang) => fetch(`/language/${lang}.json`).then((res) => res.json()),
});
loader: (lang) => fetch(`/language/${lang}.json`).then((res) => res.json())
})
import FileSaver from 'file-saver'
import * as actions from '../../components/qdn-action-types';
import '@material/mwc-button';
import '@material/mwc-icon';
import * as actions from '../../components/qdn-action-types'
import '@material/mwc-button'
import '@material/mwc-icon'
import '@material/mwc-checkbox'
import WebWorker from 'web-worker:./computePowWorkerFile.src.js';
import WebWorkerChat from 'web-worker:./computePowWorker.src.js';
import { publishData } from '../../../utils/publish-image.js';
import WebWorker from 'web-worker:./computePowWorkerFile.src.js'
import WebWorkerChat from 'web-worker:./computePowWorker.src.js'
import { publishData } from '../../../utils/publish-image.js'
import { Loader } from '../../../utils/loader.js';
import { QORT_DECIMALS } from '../../../../../crypto/api/constants';
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, decryptDeprecatedSingle, decryptGroupData, encryptData, encryptDataGroup, fileToBase64, uint8ArrayStartsWith, uint8ArrayToBase64 } from '../../components/qdn-action-encryption';
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 {
@@ -114,6 +111,10 @@ class WebBrowser extends LitElement {
font-size: 16px;
background-color: var(--white);
}
input {
outline: none
}
paper-progress {
--paper-progress-active-color: var(--mdc-theme-primary);
@@ -204,11 +205,11 @@ class WebBrowser extends LitElement {
}
this.selectedAddress = {}
this.btcFeePerByte = 100
this.ltcFeePerByte = 30
this.dogeFeePerByte = 1000
this.dgbFeePerByte = 10
this.rvnFeePerByte = 1125
this.btcFeePerByte = 0.00000100
this.ltcFeePerByte = 0.00000030
this.dogeFeePerByte = 0.00001000
this.dgbFeePerByte = 0.00000010
this.rvnFeePerByte = 0.00001125
this.arrrWalletAddress = ''
let configLoaded = false;
@@ -235,18 +236,78 @@ class WebBrowser extends LitElement {
configLoaded = true;
}
})
parentEpml.subscribe('copy_menu_switch', async (value) => {
if (
value === 'false' &&
window.getSelection().toString().length !== 0
) {
this.clearSelection();
}
})
})
}
async extractComponents(url) {
if (!url.startsWith("qortal://")) {
return null;
}
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;
if (parts.length > 0) {
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=${this.getApiKey()}`
})
if (responseObj.totalChunkCount > 0) {
// Identifier exists, so don't include it in the path
parts.shift();
}
else {
identifier = null;
}
}
const path = parts.join("/");
const components = {};
components["service"] = service;
components["name"] = name;
components["identifier"] = identifier;
components["path"] = path;
return components;
}
return null;
}
async _handleKeyDown(e) {
if (e.key === 'Enter') {
const value = e.target.value
let newQuery = value;
if (newQuery.endsWith('/')) {
newQuery = newQuery.slice(0, -1);
}
const res = await this.extractComponents(newQuery)
if (!res) return
const { service, name, identifier, path } = res
let query = `?service=${service}`
if (name) {
query = query + `&name=${name}`
}
if (identifier) {
query = query + `&identifier=${identifier}`
}
if (path) {
query = query + `&path=${path}`
}
window.location = window.location.origin + window.location.pathname + query
}
}
render() {
return html`
<div id="websitesWrapper" style="width:auto; padding:10px; background: var(--white);">
<div class="layout horizontal center">
@@ -255,7 +316,7 @@ class WebBrowser extends LitElement {
<mwc-button @click=${() => this.goForward()} title="${translate('browserpage.bchange1')}" class="address-bar-button"><mwc-icon>arrow_forward_ios</mwc-icon></mwc-button>
<mwc-button @click=${() => this.refresh()} title="${translate('browserpage.bchange2')}" class="address-bar-button"><mwc-icon>refresh</mwc-icon></mwc-button>
<mwc-button @click=${() => this.goBackToList()} title="${translate('browserpage.bchange3')}" class="address-bar-button"><mwc-icon>home</mwc-icon></mwc-button>
<input disabled style="width: 550px; color: var(--black);" id="address" type="text" value="${this.displayUrl}"></input>
<input @keydown=${this._handleKeyDown} style="width: 550px; color: var(--black);" id="address" type="text" value="${this.displayUrl}"></input>
${this.renderFullScreen()}
<mwc-button @click=${() => this.delete()} title="${translate('browserpage.bchange4')} ${this.service} ${this.name} ${translate('browserpage.bchange5')}" class="address-bar-button float-right"><mwc-icon>delete</mwc-icon></mwc-button>
${this.renderBlockUnblockButton()}
@@ -487,15 +548,6 @@ class WebBrowser extends LitElement {
this.rvnWallet = window.parent.reduxStore.getState().app.selectedAddress.rvnWallet
this.arrrWallet = window.parent.reduxStore.getState().app.selectedAddress.arrrWallet
window.addEventListener('contextmenu', (event) => {
event.preventDefault();
this._textMenu(event);
});
window.addEventListener('click', () => {
parentEpml.request('closeCopyTextMenu', null);
});
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage');
const checkTheme = localStorage.getItem('qortalTheme');
@@ -510,11 +562,13 @@ class WebBrowser extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme);
});
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null);
}
};
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
window.addEventListener('message', async (event) => {
if (
@@ -610,7 +664,7 @@ class WebBrowser extends LitElement {
response = JSON.stringify(data);
break
} catch (error) {
console.log({ error })
const data = {};
const errorMsg = error.message || "Error in decrypting data"
data['error'] = errorMsg;
@@ -833,7 +887,42 @@ class WebBrowser extends LitElement {
this.service = data.service;
this.identifier = data.identifier;
this.displayUrl = url;
const frame = window.frameElement
let tabId = ""
if (frame && frame.dataset.id) {
tabId = frame.dataset.id
}
if (data.name === 'Q-Mail') {
localStorage.setItem("Q-Mail-last-visited", Date.now())
}
window.parent.reduxStore.dispatch(window.parent.reduxAction.addTabInfo({
name: data.name,
service: data.service,
id: tabId ? tabId : ""
}))
return;
case actions.SET_TAB_NOTIFICATIONS: {
const { count } = data
if (isNaN(count)) {
response['error'] = 'count is not a number'
break
}
if (count === undefined) {
response['error'] = 'missing count'
break
}
window.parent.reduxStore.dispatch(window.parent.reduxAction.setTabNotifications({
name: this.name,
count: count
}))
response = true
break
}
case actions.PUBLISH_QDN_RESOURCE: {
// optional fields: encrypt:boolean recipientPublicKey:string
@@ -1602,62 +1691,65 @@ class WebBrowser extends LitElement {
} finally {
this.loader.hide();
}
}
// else {
// let _url = ``
// let _body = null
} else {
let _url = ``
let _body = null
// switch (coin) {
// case 'LTC':
// _url = `/crosschain/ltc/walletbalance?apiKey=${this.getApiKey()}`
// _body = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet.derivedMasterPublicKey
// break
// case 'DOGE':
// _url = `/crosschain/doge/walletbalance?apiKey=${this.getApiKey()}`
// _body = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet.derivedMasterPublicKey
// break
// case 'DGB':
// _url = `/crosschain/dgb/walletbalance?apiKey=${this.getApiKey()}`
// _body = window.parent.reduxStore.getState().app.selectedAddress.dgbWallet.derivedMasterPublicKey
// break
// case 'RVN':
// _url = `/crosschain/rvn/walletbalance?apiKey=${this.getApiKey()}`
// _body = window.parent.reduxStore.getState().app.selectedAddress.rvnWallet.derivedMasterPublicKey
// break
// case 'ARRR':
// _url = `/crosschain/arrr/walletbalance?apiKey=${this.getApiKey()}`
// _body = window.parent.reduxStore.getState().app.selectedAddress.arrrWallet.seed58
// break
// default:
// break
// }
// try {
// this.loader.show();
// const res = await parentEpml.request('apiCall', {
// url: _url,
// method: 'POST',
// body: _body,
// })
// if (isNaN(Number(res))) {
// const data = {};
// const errorMsg = error.message || get("browserpage.bchange21");
// data['error'] = errorMsg;
// response = JSON.stringify(data);
// return;
// } else {
// response = (Number(res) / 1e8).toFixed(8);
// }
// } catch (error) {
// console.error(error);
// const data = {};
// const errorMsg = error.message || get("browserpage.bchange21");
// data['error'] = errorMsg;
// response = JSON.stringify(data);
// return;
// } finally {
// this.loader.hide()
// }
// }
switch (coin) {
case 'BTC':
_url = `/crosschain/btc/walletbalance?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.btcWallet.derivedMasterPublicKey
break
case 'LTC':
_url = `/crosschain/ltc/walletbalance?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet.derivedMasterPublicKey
break
case 'DOGE':
_url = `/crosschain/doge/walletbalance?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet.derivedMasterPublicKey
break
case 'DGB':
_url = `/crosschain/dgb/walletbalance?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.dgbWallet.derivedMasterPublicKey
break
case 'RVN':
_url = `/crosschain/rvn/walletbalance?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.rvnWallet.derivedMasterPublicKey
break
case 'ARRR':
_url = `/crosschain/arrr/walletbalance?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.arrrWallet.seed58
break
default:
break
}
try {
this.loader.show();
const res = await parentEpml.request('apiCall', {
url: _url,
method: 'POST',
body: _body,
})
if (isNaN(Number(res))) {
const data = {};
const errorMsg = error.message || get("browserpage.bchange21");
data['error'] = errorMsg;
response = JSON.stringify(data);
return;
} else {
response = (Number(res) / 1e8).toFixed(8);
}
} catch (error) {
console.error(error);
const data = {};
const errorMsg = error.message || get("browserpage.bchange21");
data['error'] = errorMsg;
response = JSON.stringify(data);
return;
} finally {
this.loader.hide()
}
}
} else if (res3.action === 'reject') {
response = '{"error": "User declined request"}';
}
@@ -1727,7 +1819,7 @@ class WebBrowser extends LitElement {
let errorMsg = "Insufficient Funds!"
let failedMsg = get("walletpage.wchange26")
let pleaseMsg = get("walletpage.wchange44")
showErrorAndWait("INSSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
showErrorAndWait("INSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
let obj = {}
obj['error'] = errorMsg
response = JSON.stringify(obj)
@@ -1758,7 +1850,8 @@ class WebBrowser extends LitElement {
amount,
recipient,
coin,
balance
balance,
fee
}
)
@@ -1897,6 +1990,7 @@ class WebBrowser extends LitElement {
const recipient = data.destinationAddress
const coin = data.coin
const xprv58 = this.btcWallet.derivedMasterPrivateKey
const feePerByte = data.fee ? data.fee : this.btcFeePerByte
const btcWalletBalance = await parentEpml.request('apiCall', {
url: `/crosschain/btc/walletbalance?apiKey=${this.getApiKey()}`,
@@ -1919,14 +2013,14 @@ class WebBrowser extends LitElement {
const btcWalletBalanceDecimals = Number(btcWalletBalance)
const btcAmountDecimals = Number(amount) * QORT_DECIMALS
const balance = (Number(btcWalletBalance) / 1e8).toFixed(8)
const fee = 50000
const fee = feePerByte * 500 // default 0.00050000
if (btcAmountDecimals + fee > btcWalletBalanceDecimals) {
if (btcAmountDecimals + (fee * QORT_DECIMALS) > btcWalletBalanceDecimals) {
this.loader.hide()
let errorMsg = "Insufficient Funds!"
let failedMsg = get("walletpage.wchange26")
let pleaseMsg = get("walletpage.wchange44")
showErrorAndWait("INSSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
showErrorAndWait("INSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
let obj = {}
obj['error'] = errorMsg
response = JSON.stringify(obj)
@@ -1941,7 +2035,8 @@ class WebBrowser extends LitElement {
amount,
recipient,
coin,
balance
balance,
fee
}
)
@@ -1961,7 +2056,7 @@ class WebBrowser extends LitElement {
xprv58: xprv58,
receivingAddress: recipient,
bitcoinAmount: amount,
feePerByte: (this.btcFeePerByte / 1e8).toFixed(8)
feePerByte: feePerByte * QORT_DECIMALS
}
const response = await parentEpml.request('sendBtc', opts)
return response
@@ -2003,6 +2098,7 @@ class WebBrowser extends LitElement {
const recipient = data.destinationAddress
const coin = data.coin
const xprv58 = this.ltcWallet.derivedMasterPrivateKey
const feePerByte = data.fee ? data.fee : this.ltcFeePerByte
const ltcWalletBalance = await parentEpml.request('apiCall', {
url: `/crosschain/ltc/walletbalance?apiKey=${this.getApiKey()}`,
@@ -2025,14 +2121,14 @@ class WebBrowser extends LitElement {
const ltcWalletBalanceDecimals = Number(ltcWalletBalance)
const ltcAmountDecimals = Number(amount) * QORT_DECIMALS
const balance = (Number(ltcWalletBalance) / 1e8).toFixed(8)
const fee = 30000
const fee = feePerByte * 1000 // default 0.00030000
if (ltcAmountDecimals + fee > ltcWalletBalanceDecimals) {
if (ltcAmountDecimals + (fee * QORT_DECIMALS) > ltcWalletBalanceDecimals) {
this.loader.hide()
let errorMsg = "Insufficient Funds!"
let failedMsg = get("walletpage.wchange26")
let pleaseMsg = get("walletpage.wchange44")
showErrorAndWait("INSSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
showErrorAndWait("INSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
let obj = {}
obj['error'] = errorMsg
response = JSON.stringify(obj)
@@ -2047,7 +2143,8 @@ class WebBrowser extends LitElement {
amount,
recipient,
coin,
balance
balance,
fee
}
)
@@ -2067,7 +2164,7 @@ class WebBrowser extends LitElement {
xprv58: xprv58,
receivingAddress: recipient,
litecoinAmount: amount,
feePerByte: (this.ltcFeePerByte / 1e8).toFixed(8)
feePerByte: feePerByte * QORT_DECIMALS
}
const response = await parentEpml.request('sendLtc', opts)
return response
@@ -2109,6 +2206,7 @@ class WebBrowser extends LitElement {
const recipient = data.destinationAddress
const coin = data.coin
const xprv58 = this.dogeWallet.derivedMasterPrivateKey
const feePerByte = data.fee ? data.fee : this.dogeFeePerByte
const dogeWalletBalance = await parentEpml.request('apiCall', {
url: `/crosschain/doge/walletbalance?apiKey=${this.getApiKey()}`,
@@ -2131,14 +2229,14 @@ class WebBrowser extends LitElement {
const dogeWalletBalanceDecimals = Number(dogeWalletBalance)
const dogeAmountDecimals = Number(amount) * QORT_DECIMALS
const balance = (Number(dogeWalletBalance) / 1e8).toFixed(8)
const fee = 5000000
const fee = feePerByte * 5000 // default 0.05000000
if (dogeAmountDecimals + fee > dogeWalletBalanceDecimals) {
if (dogeAmountDecimals + (fee * QORT_DECIMALS) > dogeWalletBalanceDecimals) {
this.loader.hide()
let errorMsg = "Insufficient Funds!"
let failedMsg = get("walletpage.wchange26")
let pleaseMsg = get("walletpage.wchange44")
showErrorAndWait("INSSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
showErrorAndWait("INSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
let obj = {}
obj['error'] = errorMsg
response = JSON.stringify(obj)
@@ -2153,7 +2251,8 @@ class WebBrowser extends LitElement {
amount,
recipient,
coin,
balance
balance,
fee
}
)
@@ -2173,7 +2272,7 @@ class WebBrowser extends LitElement {
xprv58: xprv58,
receivingAddress: recipient,
dogecoinAmount: amount,
feePerByte: (this.dogeFeePerByte / 1e8).toFixed(8)
feePerByte: feePerByte * QORT_DECIMALS
}
const response = await parentEpml.request('sendDoge', opts)
return response
@@ -2215,6 +2314,7 @@ class WebBrowser extends LitElement {
const recipient = data.destinationAddress
const coin = data.coin
const xprv58 = this.dgbWallet.derivedMasterPrivateKey
const feePerByte = data.fee ? data.fee : this.dgbFeePerByte
const dgbWalletBalance = await parentEpml.request('apiCall', {
url: `/crosschain/dgb/walletbalance?apiKey=${this.getApiKey()}`,
@@ -2237,14 +2337,14 @@ class WebBrowser extends LitElement {
const dgbWalletBalanceDecimals = Number(dgbWalletBalance)
const dgbAmountDecimals = Number(amount) * QORT_DECIMALS
const balance = (Number(dgbWalletBalance) / 1e8).toFixed(8)
const fee = 5000
const fee = feePerByte * 500 // default 0.00005000
if (dgbAmountDecimals + fee > dgbWalletBalanceDecimals) {
if (dgbAmountDecimals + (fee * QORT_DECIMALS) > dgbWalletBalanceDecimals) {
this.loader.hide()
let errorMsg = "Insufficient Funds!"
let failedMsg = get("walletpage.wchange26")
let pleaseMsg = get("walletpage.wchange44")
showErrorAndWait("INSSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
showErrorAndWait("INSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
let obj = {}
obj['error'] = errorMsg
response = JSON.stringify(obj)
@@ -2259,7 +2359,8 @@ class WebBrowser extends LitElement {
amount,
recipient,
coin,
balance
balance,
fee
}
)
@@ -2279,7 +2380,7 @@ class WebBrowser extends LitElement {
xprv58: xprv58,
receivingAddress: recipient,
digibyteAmount: amount,
feePerByte: (this.dgbFeePerByte / 1e8).toFixed(8)
feePerByte: feePerByte * QORT_DECIMALS
}
const response = await parentEpml.request('sendDgb', opts)
return response
@@ -2321,6 +2422,7 @@ class WebBrowser extends LitElement {
const recipient = data.destinationAddress
const coin = data.coin
const xprv58 = this.rvnWallet.derivedMasterPrivateKey
const feePerByte = data.fee ? data.fee : this.rvnFeePerByte
const rvnWalletBalance = await parentEpml.request('apiCall', {
url: `/crosschain/rvn/walletbalance?apiKey=${this.getApiKey()}`,
@@ -2343,14 +2445,14 @@ class WebBrowser extends LitElement {
const rvnWalletBalanceDecimals = Number(rvnWalletBalance)
const rvnAmountDecimals = Number(amount) * QORT_DECIMALS
const balance = (Number(rvnWalletBalance) / 1e8).toFixed(8)
const fee = 562500
const fee = feePerByte * 500 // default 0.00562500
if (rvnAmountDecimals + fee > rvnWalletBalanceDecimals) {
if (rvnAmountDecimals + (fee * QORT_DECIMALS) > rvnWalletBalanceDecimals) {
this.loader.hide()
let errorMsg = "Insufficient Funds!"
let failedMsg = get("walletpage.wchange26")
let pleaseMsg = get("walletpage.wchange44")
showErrorAndWait("INSSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
showErrorAndWait("INSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
let obj = {}
obj['error'] = errorMsg
response = JSON.stringify(obj)
@@ -2365,7 +2467,8 @@ class WebBrowser extends LitElement {
amount,
recipient,
coin,
balance
balance,
fee
}
)
@@ -2385,7 +2488,7 @@ class WebBrowser extends LitElement {
xprv58: xprv58,
receivingAddress: recipient,
ravencoinAmount: amount,
feePerByte: (this.rvnFeePerByte / 1e8).toFixed(8)
feePerByte: feePerByte * QORT_DECIMALS
}
const response = await parentEpml.request('sendRvn', opts)
return response
@@ -2450,14 +2553,14 @@ class WebBrowser extends LitElement {
const arrrWalletBalanceDecimals = Number(arrrWalletBalance)
const arrrAmountDecimals = Number(amount) * QORT_DECIMALS
const balance = (Number(arrrWalletBalance) / 1e8).toFixed(8)
const fee = 10000
const fee = 0.00010000
if (arrrAmountDecimals + fee > arrrWalletBalanceDecimals) {
if (arrrAmountDecimals + (fee * QORT_DECIMALS) > arrrWalletBalanceDecimals) {
this.loader.hide()
let errorMsg = "Insufficient Funds!"
let failedMsg = get("walletpage.wchange26")
let pleaseMsg = get("walletpage.wchange44")
showErrorAndWait("INSSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
showErrorAndWait("INSUFFICIENT_FUNDS", failedMsg, pleaseMsg)
let obj = {}
obj['error'] = errorMsg
response = JSON.stringify(obj)
@@ -2472,7 +2575,8 @@ class WebBrowser extends LitElement {
amount,
recipient,
coin,
balance
balance,
fee
}
)
@@ -2819,40 +2923,6 @@ class WebBrowser extends LitElement {
return ret;
}
_textMenu(event) {
const getSelectedText = () => {
var text = '';
if (typeof window.getSelection != 'undefined') {
text = window.getSelection().toString();
} else if (
typeof this.shadowRoot.selection != 'undefined' &&
this.shadowRoot.selection.type == 'Text'
) {
text = this.shadowRoot.selection.createRange().text;
}
return text;
};
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = {
pageX: event.pageX,
pageY: event.pageY,
clientX: event.clientX,
clientY: event.clientY,
};
let textMenuObject = {
selectedText: selectedText,
eventObject: _eve,
isFrame: true,
};
parentEpml.request('openCopyTextMenu', textMenuObject);
}
};
checkSelectedTextAndShowMenu();
}
getApiKey() {
const myNode =
window.parent.reduxStore.getState().app.nodeConfig.knownNodes[
@@ -2861,11 +2931,6 @@ class WebBrowser extends LitElement {
let apiKey = myNode.apiKey;
return apiKey;
}
clearSelection() {
window.getSelection().removeAllRanges();
window.parent.getSelection().removeAllRanges();
}
}
window.customElements.define('web-browser', WebBrowser);
@@ -2942,6 +3007,7 @@ async function showModalAndWait(type, data) {
<p style="font-size: 16px;overflow-wrap: anywhere;" class="modal-paragraph"><span style="font-weight: bold">${get("walletpage.wchange19")}:</span> ${data.balance} ${data.coin}</p>
<p style="font-size: 16px;overflow-wrap: anywhere;" class="modal-paragraph"><span style="font-weight: bold">${get("walletpage.wchange10")}:</span> ${data.recipient}</p>
<p style="font-size: 16px;overflow-wrap: anywhere;" class="modal-paragraph"><span style="font-weight: bold">${get("walletpage.wchange11")}:</span> ${data.amount} ${data.coin}</p>
<p style="font-size: 16px;overflow-wrap: anywhere;" class="modal-paragraph"><span style="font-weight: bold">${get("walletpage.wchange36")}:</span> ~${data.fee} ${data.coin}</p>
</div>
` : ''}
@@ -3087,7 +3153,7 @@ async function showErrorAndWait(type, data, data1) {
</div>
` : ''}
${type === "INSSUFFICIENT_FUNDS" ? `
${type === "INSUFFICIENT_FUNDS" ? `
<div class="modal-subcontainer-error">
<p class="modal-paragraph-error">${data}</p>
<p class="modal-paragraph-error">${data1}</p>

View File

@@ -1,6 +1,7 @@
import { LitElement, html, css } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../../epml'
import isElectron from 'is-electron'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
registerTranslateConfig({
@@ -445,15 +446,6 @@ class DataManagement extends LitElement {
this.changeLanguage()
this.showManagement()
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
this._textMenu(event)
})
window.addEventListener('click', () => {
parentEpml.request('closeCopyTextMenu', null)
})
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
@@ -468,10 +460,12 @@ class DataManagement extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
let configLoaded = false
@@ -498,13 +492,6 @@ class DataManagement extends LitElement {
configLoaded = true
}
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
})
parentEpml.imReady()
}
@@ -980,29 +967,6 @@ class DataManagement extends LitElement {
return ret
}
_textMenu(event) {
const getSelectedText = () => {
var text = ''
if (typeof window.getSelection != 'undefined') {
text = window.getSelection().toString()
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
text = this.shadowRoot.selection.createRange().text
}
return text
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText()
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
async getResourcesGrid() {
this.resourcesGrid = this.shadowRoot.querySelector(`#resourcesGrid`)
this.pagesControl = this.shadowRoot.querySelector('#pages')
@@ -1123,11 +1087,6 @@ class DataManagement extends LitElement {
return apiKey;
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
isEmptyArray(arr) {
if (!arr) { return true }
return arr.length === 0

View File

@@ -1,6 +1,7 @@
import { LitElement, html, css } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../../epml'
import isElectron from 'is-electron'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
registerTranslateConfig({
@@ -241,12 +242,6 @@ class PublishData extends LitElement {
}
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
})
}
@@ -327,15 +322,6 @@ class PublishData extends LitElement {
this.changeTheme()
this.changeLanguage()
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
this._textMenu(event)
})
window.addEventListener('click', () => {
parentEpml.request('closeCopyTextMenu', null)
})
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
@@ -350,10 +336,12 @@ class PublishData extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
}
@@ -679,29 +667,6 @@ class PublishData extends LitElement {
validate()
}
_textMenu(event) {
const getSelectedText = () => {
var text = ''
if (typeof window.getSelection != 'undefined') {
text = window.getSelection().toString()
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
text = this.shadowRoot.selection.createRange().text
}
return text
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText()
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
fetchResourceMetadata() {
let identifier = this.identifier != null ? this.identifier : "default"
@@ -736,11 +701,6 @@ class PublishData extends LitElement {
let apiKey = myNode.apiKey
return apiKey
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
}
window.customElements.define('publish-data', PublishData)

View File

@@ -1,12 +1,14 @@
import { LitElement, html, css } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../epml.js'
import isElectron from 'is-electron'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
})
import '@material/mwc-dialog'
import '@material/mwc-icon'
import '@material/mwc-button'
import '@material/mwc-tab-bar'
@@ -44,6 +46,17 @@ class Websites extends LitElement {
return css`
* {
--mdc-theme-primary: rgb(3, 169, 244);
--mdc-button-disabled-fill-color: rgba(3, 169, 244, 0.5);
--mdc-theme-surface: var(--white);
--mdc-text-field-outlined-idle-border-color: var(--txtfieldborder);
--mdc-text-field-outlined-hover-border-color: var(--txtfieldhoverborder);
--mdc-text-field-label-ink-color: var(--black);
--mdc-text-field-ink-color: var(--black);
--mdc-dialog-content-ink-color: var(--black);
--mdc-dialog-shape-radius: 25px;
--mdc-dialog-min-width: 300px;
--mdc-dialog-max-width: auto;
--mdc-dialog-max-height: 700px;
--paper-input-container-focus-color: var(--mdc-theme-primary);
--lumo-primary-text-color: rgb(0, 167, 245);
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
@@ -245,45 +258,11 @@ class Websites extends LitElement {
</mwc-tab-bar>
<div id="tabs-1-content">
<div id="tab-browse-content">
<div style="min-height:48px; display: flex; padding-bottom: 6px; margin: 2px;">
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${translate("websitespage.schange1")}</h2>
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
</div>
<div class="divCard">
<h3 style="margin: 0; margin-bottom: 1em; text-align: left;">${translate("websitespage.schange4")}</h3>
<div id="search">
<vaadin-text-field theme="medium" id="searchName" placeholder="${translate("websitespage.schange33")}" value="${this.searchName}" @keydown="${this.searchListener}" clear-button-visible>
<vaadin-icon slot="prefix" icon="vaadin:user"></vaadin-icon>
</vaadin-text-field>&nbsp;&nbsp;<br>
<vaadin-button theme="medium" @click="${(e) => this.doSearch(e)}">
<vaadin-icon icon="vaadin:search" slot="prefix"></vaadin-icon>
${translate("websitespage.schange35")}
</vaadin-button>
</div><br />
<vaadin-grid theme="wrap-cell-content" id="searchResourcesGrid" ?hidden="${this.isEmptyArray(this.searchResources)}" .items="${this.searchResources}" aria-label="Search Websites" all-rows-visible>
<vaadin-grid-column width="7rem" flex-grow="0" header="${translate("websitespage.schange5")}" .renderer=${(root, column, data) => {
render(html`${this.renderAvatar(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column header="${translate("websitespage.schange6")}" .renderer=${(root, column, data) => {
render(html`${this.renderInfo(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="12rem" flex-grow="0" header="${translate("websitespage.schange7")}" .renderer=${(root, column, data) => {
render(html`${this.renderPublishedBy(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="11rem" flex-grow="0" header="${translate("websitespage.schange8")}" .renderer=${(root, column, data) => {
render(html`${this.renderFollowUnfollowButton(data.item)}`, root);
}}>
</vaadin-grid-column>
<vaadin-grid-column width="11rem" flex-grow="0" header="" .renderer=${(root, column, data) => {
render(html`${this.renderBlockUnblockButton(data.item)}`, root);
}}>
</vaadin-grid-column>
</vaadin-grid><br />
</div>
<div class="divCard">
<div style="min-height:48px; display: flex; padding-bottom: 6px; margin: 2px;">
<h2 style="margin: 0; padding-top: .5em; display: inline;">${translate("websitespage.schange1")}</h2>
<h2 style="margin: 0; flex: 6; padding-top: .5em; display: inline;">${this.renderSearchButton()}</h2>
<h2 style="margin: 0; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
</div>
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">${translate("websitespage.schange9")}</h3>
<vaadin-grid theme="wrap-cell-content" id="resourcesGrid" ?hidden="${this.isEmptyArray(this.pageRes)}" .items="${this.pageRes}" aria-label="Websites" all-rows-visible>
<vaadin-grid-column width="7rem" flex-grow="0" header="${translate("websitespage.schange5")}" .renderer=${(root, column, data) => {
@@ -314,13 +293,13 @@ class Websites extends LitElement {
${this.isEmptyArray(this.pageRes) ? html`
<span style="color: var(--black);">${translate("websitespage.schange10")}</span>
` : ''}
</div>
${this.renderRelayModeText()}
</div>
<div id="tab-followed-content">
<div style="min-height:48px; display: flex; padding-bottom: 6px; margin: 2px;">
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${translate("websitespage.schange11")}</h2>
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
<h2 style="margin: 0; padding-top: .5em; display: inline;">${translate("websitespage.schange11")}</h2>
<h2 style="margin: 0; flex: 6; padding-top: .5em; display: inline;">${this.renderSearchButton()}</h2>
<h2 style="margin: 0; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
</div>
<div class="divCard">
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">${translate("websitespage.schange12")}</h3>
@@ -348,15 +327,14 @@ class Websites extends LitElement {
${this.isEmptyArray(this.followedResources) ? html`
<span style="color: var(--black);">${translate("websitespage.schange13")}</span>
` : ''}
</div>
${this.renderRelayModeText()}
</div>
<div id="tab-blocked-content">
<div style="min-height:48px; display: flex; padding-bottom: 6px; margin: 2px;">
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${translate("websitespage.schange14")}</h2>
<h2 style="margin: 0; flex: 1; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
<h2 style="margin: 0; padding-top: .5em; display: inline;">${translate("websitespage.schange14")}</h2>
<h2 style="margin: 0; flex: 6; padding-top: .5em; display: inline;">${this.renderSearchButton()}</h2>
<h2 style="margin: 0; padding-top: .5em; display: inline;">${this.renderPublishButton()}</h2>
</div>
<div class="divCard">
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">${translate("websitespage.schange15")}</h3>
<vaadin-grid theme="wrap-cell-content" id="blockedResourcesGrid" ?hidden="${this.isEmptyArray(this.blockedResources)}" .items="${this.blockedResources}" aria-label="Blocked Websites" all-rows-visible>
<vaadin-grid-column width="7rem" flex-grow="0" header="${translate("websitespage.schange5")}" .renderer=${(root, column, data) => {
@@ -382,11 +360,40 @@ class Websites extends LitElement {
${this.isEmptyArray(this.blockedResources) ? html`
<span style="color: var(--black);">${translate("websitespage.schange16")}</span>
` : ''}
</div>
${this.renderRelayModeText()}
</div>
</div>
</div>
<mwc-dialog id="searchWebsiteDialog">
<h3 style="margin: 0; margin-bottom: 1em; text-align: left;">${translate("websitespage.schange4")}</h3>
<div id="search">
<vaadin-text-field theme="medium" id="searchName" placeholder="${translate("websitespage.schange33")}" value="${this.searchName}" @keydown="${this.searchListener}" clear-button-visible>
<vaadin-icon slot="prefix" icon="vaadin:user"></vaadin-icon>
</vaadin-text-field>&nbsp;&nbsp;<br>
<vaadin-button theme="medium" @click="${(e) => this.doSearch(e)}">
<vaadin-icon icon="vaadin:search" slot="prefix"></vaadin-icon>
${translate("websitespage.schange35")}
</vaadin-button>
</div><br />
<vaadin-grid theme="wrap-cell-content" id="searchResourcesGrid" ?hidden="${this.isEmptyArray(this.searchResources)}" .items="${this.searchResources}" aria-label="Search Websites" all-rows-visible>
<vaadin-grid-column width="7rem" flex-grow="0" header="${translate("websitespage.schange5")}" .renderer=${(root, column, data) => {
render(html`${this.renderAvatar(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="12rem" flex-grow="0" header="${translate("websitespage.schange7")}" .renderer=${(root, column, data) => {
render(html`${this.renderPublishedBy(data.item)}`, root)
}}>
</vaadin-grid-column>
<vaadin-grid-column width="11rem" flex-grow="0" header="${translate("websitespage.schange8")}" .renderer=${(root, column, data) => {
render(html`${this.renderFollowUnfollowButton(data.item)}`, root);
}}>
</vaadin-grid-column>
<vaadin-grid-column width="11rem" flex-grow="0" header="" .renderer=${(root, column, data) => {
render(html`${this.renderBlockUnblockButton(data.item)}`, root);
}}>
</vaadin-grid-column>
</vaadin-grid>
</mwc-dialog>
`
}
@@ -426,21 +433,6 @@ class Websites extends LitElement {
setTimeout(getRelayMode, 600000)
}
window.addEventListener("contextmenu", (event) => {
event.preventDefault();
this._textMenu(event)
});
window.addEventListener("click", () => {
parentEpml.request('closeCopyTextMenu', null)
});
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
}
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
@@ -455,6 +447,14 @@ class Websites extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
let configLoaded = false
parentEpml.ready().then(() => {
@@ -476,11 +476,6 @@ class Websites extends LitElement {
}
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
})
parentEpml.imReady()
}
@@ -739,6 +734,16 @@ class Websites extends LitElement {
return html`<mwc-button style="float:right;" @click=${() => this.publishWebsite()}><mwc-icon>add</mwc-icon>${translate("websitespage.schange21")}</mwc-button>`
}
renderSearchButton() {
return html`<mwc-button style="float:right;" @click=${() => this.openSearchDialog()}><mwc-icon>search</mwc-icon>${translate("websitespage.schange4")}</mwc-button>`
}
openSearchDialog() {
this.searchResources = []
this.shadowRoot.getElementById('searchName').value = ''
this.shadowRoot.getElementById('searchWebsiteDialog').show()
}
publishWebsite() {
window.location.href = `publish/index.html?service=${this.service}&identifier=${this.identifier}&uploadType=zip&category=Website&showName=true&showService=false&showIdentifier=false&showMetadata=true`
}
@@ -1101,39 +1106,12 @@ class Websites extends LitElement {
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i]
}
_textMenu(event) {
const getSelectedText = () => {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text;
}
return text
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
getApiKey() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let apiKey = myNode.apiKey
return apiKey
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
isEmptyArray(arr) {
if (!arr) { return true }
return arr.length === 0

View File

@@ -1,6 +1,7 @@
import { LitElement, html, css } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../epml.js'
import isElectron from 'is-electron'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
registerTranslateConfig({
@@ -214,15 +215,6 @@ class RewardShare extends LitElement {
this.changeTheme()
this.changeLanguage()
window.addEventListener("contextmenu", (event) => {
event.preventDefault()
this._textMenu(event)
})
window.addEventListener("click", () => {
parentEpml.request('closeCopyTextMenu', null)
})
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
@@ -237,14 +229,14 @@ class RewardShare extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
const textBox = this.shadowRoot.getElementById("recipientPublicKey")
const updateRewardshares = () => {
parentEpml.request('apiCall', {
url: `/addresses/rewardshares?involving=${this.selectedAddress.address}`
@@ -271,51 +263,9 @@ class RewardShare extends LitElement {
}
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
parentEpml.subscribe('frame_paste_menu_switch', async res => {
res = JSON.parse(res)
if (res.isOpen === false && this.isPasteMenuOpen === true) {
this.pasteToTextBox(textBox)
this.isPasteMenuOpen = false
}
})
})
parentEpml.imReady()
textBox.addEventListener('contextmenu', (event) => {
const getSelectedText = () => {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text;
}
return text;
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
// ...
} else {
this.pasteMenu(event)
this.isPasteMenuOpen = true
// Prevent Default and Stop Event Bubbling
event.preventDefault()
event.stopPropagation()
}
}
checkSelectedTextAndShowMenu()
})
}
changeTheme() {
@@ -733,57 +683,10 @@ class RewardShare extends LitElement {
removeReceiver()
}
pasteToTextBox(textBox) {
// Return focus to the window
window.focus()
navigator.clipboard.readText().then(clipboardText => {
textBox.value += clipboardText
textBox.focus()
});
}
pasteMenu(event) {
let eventObject = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
parentEpml.request('openFramePasteMenu', eventObject)
}
_textMenu(event) {
const getSelectedText = () => {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof this.shadowRoot.selection != "undefined" && this.shadowRoot.selection.type == "Text") {
text = this.shadowRoot.selection.createRange().text;
}
return text;
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText();
if (selectedText && typeof selectedText === 'string') {
let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
isEmptyArray(arr) {
if (!arr) { return true }
return arr.length === 0
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
}
window.customElements.define('reward-share', RewardShare)

View File

@@ -4,6 +4,7 @@ import "../components/ButtonIconCopy.js"
import { use, get, translate, registerTranslateConfig } from "lit-translate"
import { blocksNeed } from "../../utils/blocks-needed.js"
import "../components/ButtonIconCopy.js"
import isElectron from 'is-electron'
registerTranslateConfig({
loader: (lang) => fetch(`/language/${lang}.json`).then((res) => res.json()),
@@ -226,6 +227,13 @@ class SponsorshipList extends LitElement {
async firstUpdated() {
await this.atMount()
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
}
async getRewardShareRelationship(recipientAddress) {

View File

@@ -115,6 +115,7 @@ let closeGracefully = false
let onceLoggedIn = false
let retryOnClose = false
let canPing = false
let timeoutId
parentEpml.subscribe('logged_in', async isLoggedIn => {
@@ -127,18 +128,16 @@ 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}`;
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}`;
activeChatSocketLink = `ws://${nodeUrl}/websockets/chat/active/${window.parent.reduxStore.getState().app.selectedAddress.address}?encoding=BASE64`;
}
const activeChatSocket = new WebSocket(activeChatSocketLink);
// Open Connection
activeChatSocket.onopen = () => {
console.log(`[SOCKET]: Connected.`);
socketObject = activeChatSocket
initial = initial + 1
@@ -147,28 +146,26 @@ parentEpml.subscribe('logged_in', async isLoggedIn => {
// Message Event
activeChatSocket.onmessage = (e) => {
if (e.data === 'pong') {
clearTimeout(timeoutId);
activeChatSocketTimeout = setTimeout(pingActiveChatSocket, 45000)
return
}
try {
chatHeadWatcher(JSON.parse(e.data))
} catch (error) {
}
chatHeadWatcher(JSON.parse(e.data))
}
// Closed Event
activeChatSocket.onclose = () => {
console.log(`[SOCKET]: CLOSED`);
clearInterval(activeChatSocketTimeout)
if (closeGracefully === false && initial <= 52) {
if (initial <= 52) {
parentEpml.request('showSnackBar', "Connection to the Qortal Core was lost, is your Core running ?")
retryOnClose = true
setTimeout(pingActiveChatSocket, 10000)
initial = initial + 1
} else {
parentEpml.request('showSnackBar', "Cannot connect to the Qortal Core, restart UI and Core!")
}
if (closeGracefully === false) {
retryOnClose = true
setTimeout(pingActiveChatSocket, 10000)
}
}
@@ -188,18 +185,21 @@ parentEpml.subscribe('logged_in', async isLoggedIn => {
initChatHeadSocket()
onceLoggedIn = true
activeChatSocketTimeout = setTimeout(pingActiveChatSocket, 295000)
activeChatSocketTimeout = setTimeout(pingActiveChatSocket, 45000)
} else if (retryOnClose) {
retryOnClose = false
clearTimeout(activeChatSocketTimeout)
initChatHeadSocket()
onceLoggedIn = true
activeChatSocketTimeout = setTimeout(pingActiveChatSocket, 295000)
activeChatSocketTimeout = setTimeout(pingActiveChatSocket, 45000)
} else if (canPing) {
socketObject.send('ping')
activeChatSocketTimeout = setTimeout(pingActiveChatSocket, 295000)
timeoutId = setTimeout(() => {
socketObject.close();
clearTimeout(activeChatSocketTimeout)
}, 5000);
}
} else {

View File

@@ -1,7 +1,10 @@
import { LitElement, html, css } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../epml.js'
import isElectron from 'is-electron'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
import Base58 from '../../../../crypto/api/deps/Base58.js'
import { encryptData, decryptData } from '../../../../core/src/lockScreen.js'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
@@ -23,6 +26,7 @@ import '@polymer/paper-icon-button/paper-icon-button.js'
import '@polymer/paper-spinner/paper-spinner-lite.js'
import '@vaadin/grid'
import '@vaadin/grid/vaadin-grid-sorter'
import '@vaadin/password-field'
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
@@ -75,7 +79,16 @@ class TradeBotPortal extends LitElement {
tradeBotDogeBook: { type: Array },
tradeBotDgbBook: { type: Array },
tradeBotRvnBook: { type: Array },
tradeBotArrrBook: { type: Array }
tradeBotArrrBook: { type: Array },
autoSalt: { type: String },
autoStorageData: { type: String },
autoLockScreenPass: { type: String },
autoLockScreenSet: { type: String },
autoLockPass: { type: String },
autoLockSet: { type: String },
myAutoLockScreenPass: { type: String },
myAutoLockScreenSet: { type: String },
autoHelperMessage: { type: String }
}
}
@@ -85,17 +98,17 @@ class TradeBotPortal extends LitElement {
--mdc-theme-primary: rgb(3, 169, 244);
--mdc-theme-secondary: var(--mdc-theme-primary);
--mdc-theme-error: rgb(255, 89, 89);
--mdc-text-field-outlined-idle-border-color: var(--txtfieldborder);
--mdc-text-field-outlined-idle-border-color: var(--txtfieldborder);
--mdc-text-field-outlined-hover-border-color: var(--txtfieldhoverborder);
--mdc-text-field-label-ink-color: var(--black);
--mdc-text-field-ink-color: var(--black);
--mdc-select-outlined-idle-border-color: var(--txtfieldborder);
--mdc-select-outlined-idle-border-color: var(--txtfieldborder);
--mdc-select-outlined-hover-border-color: var(--txtfieldhoverborder);
--mdc-select-label-ink-color: var(--black);
--mdc-select-ink-color: var(--black);
--mdc-theme-surface: var(--white);
--mdc-dialog-content-ink-color: var(--black);
--mdc-dialog-shape-radius: 25px;
--mdc-dialog-shape-radius: 25px;
--paper-input-container-focus-color: var(--mdc-theme-primary);
--lumo-primary-text-color: rgb(0, 167, 245);
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
@@ -568,6 +581,56 @@ class TradeBotPortal extends LitElement {
.close-icon:hover {
cursor: pointer;
opacity: .6;
}
.setpass-wrapper {
width: 100%;
min-width: 400px;
max-width: 450px;
text-align: center;
background: var(--white);
border: 1px solid var(--black);
border-radius: 15px;
padding: 10px 10px 0px;
box-shadow: 0px 10px 15px rgba(0, 0, 0, 0.1);
}
.lock-wrapper {
width: 100%;
height: 100%;
min-width: 600px;
max-width: 600px;
min-height: 400px;
max-height: 400px;
text-align: center;
background: url("/img/qortal-lock.jpg");
border: 1px solid var(--black);
border-radius: 25px;
padding: 10px 10px 0px;
}
.text-wrapper {
width: 100%;
height: 100%;
min-width: 280px;
max-width: 280px;
min-height: 64px;
max-height: 64px;
text-align: center;
margin-left: 35px;
margin-top: 125px;
overflow: hidden;
}
.lock-title-white {
font-family: 'magistralbold';
font-weight: 700;
font-size: 26px;
line-height: 32px;
color: #ffffff;
}
.lock-title-red {
font-family: 'magistralbold';
font-weight: 700;
font-size: 26px;
line-height: 32px;
color: #df3636;
}
@media (min-width: 701px) {
* {
@@ -826,6 +889,15 @@ class TradeBotPortal extends LitElement {
this.tradeBotDgbBook = []
this.tradeBotRvnBook = []
this.tradeBotArrrBook = []
this.autoSalt = ''
this.autoStorageData = ''
this.autoLockScreenPass = ''
this.autoLockScreenSet = ''
this.autoLockPass = ''
this.autoLockSet = ''
this.myAutoLockScreenPass = ''
this.myAutoLockScreenSet = ''
this.autoHelperMessage = ''
}
openTradesTemplate() {
@@ -1469,11 +1541,14 @@ class TradeBotPortal extends LitElement {
<mwc-list-item value="DOGECOIN"><span class="coinName doge" style="color: var(--black);">DOGE / QORT</span></mwc-list-item>
<mwc-list-item value="DIGIBYTE"><span class="coinName dgb" style="color: var(--black);">DGB / QORT</span></mwc-list-item>
<mwc-list-item value="RAVENCOIN"><span class="coinName rvn" style="color: var(--black);">RVN / QORT</span></mwc-list-item>
<mwc-list-item value="PIRATECHAIN"><span class="coinName arrr" style="color: var(--black);">ARRR / QORT</span></mwc-list-item>
<mwc-list-item value="PIRATECHAIN"><span class="coinName arrr" style="color: var(--black);">ARRR / QORT</span></mwc-list-item>
</mwc-select>
<div style="padding-left: 20px; padding-top: 5px;">
<mwc-fab mini icon="info" title="${translate("info.inf7")}" @click=${() => this.shadowRoot.getElementById('buyInfoDialog').open()}></mwc-fab>
</div>
<div style="padding-left: 20px; padding-top: 5px;">
<mwc-fab mini icon="info" title="${translate("info.inf7")}" @click=${() => this.shadowRoot.getElementById('buyInfoDialog').open()}></mwc-fab>
</div>
<div style="padding-left: 10px; padding-top: 12px; color: var(--black);">
${this.renderAutoLockButton()}
</div>
</div>
<div></div>
</div>
@@ -1556,10 +1631,10 @@ class TradeBotPortal extends LitElement {
style="width: 100%; color: var(--black);"
id="autoBuyBTCTotalInput"
required
readOnly
label=""
placeholder="0.0000000"
type="number"
@input="${(e) => { this.checkTradeBotTotalAmount(e) }}"
auto-validate="false"
outlined
value="${this.initialAmount}"
@@ -1631,10 +1706,10 @@ class TradeBotPortal extends LitElement {
style="width: 100%; color: var(--black);"
id="autoBuyLTCTotalInput"
required
readOnly
label=""
placeholder="0.0000000"
type="number"
@input="${(e) => { this.checkTradeBotTotalAmount(e) }}"
auto-validate="false"
outlined
value="${this.initialAmount}"
@@ -1706,10 +1781,10 @@ class TradeBotPortal extends LitElement {
style="width: 100%; color: var(--black);"
id="autoBuyDOGETotalInput"
required
readOnly
label=""
placeholder="0.0000000"
type="number"
@input="${(e) => { this.checkTradeBotTotalAmount(e) }}"
auto-validate="false"
outlined
value="${this.initialAmount}"
@@ -1781,10 +1856,10 @@ class TradeBotPortal extends LitElement {
style="width: 100%; color: var(--black);"
id="autoBuyDGBTotalInput"
required
readOnly
label=""
placeholder="0.0000000"
type="number"
@input="${(e) => { this.checkTradeBotTotalAmount(e) }}"
auto-validate="false"
outlined
value="${this.initialAmount}"
@@ -1856,10 +1931,10 @@ class TradeBotPortal extends LitElement {
style="width: 100%; color: var(--black);"
id="autoBuyRVNTotalInput"
required
readOnly
label=""
placeholder="0.0000000"
type="number"
@input="${(e) => { this.checkTradeBotTotalAmount(e) }}"
auto-validate="false"
outlined
value="${this.initialAmount}"
@@ -1931,10 +2006,10 @@ class TradeBotPortal extends LitElement {
style="width: 100%; color: var(--black);"
id="autoBuyARRRTotalInput"
required
readOnly
label=""
placeholder="0.0000000"
type="number"
@input="${(e) => { this.checkTradeBotTotalAmount(e) }}"
auto-validate="false"
outlined
value="${this.initialAmount}"
@@ -1968,6 +2043,59 @@ class TradeBotPortal extends LitElement {
<h2>${translate("info.inf12")}</h2>
</div>
</paper-dialog>
<paper-dialog class="setpass-wrapper" id="setAutoLockScreenPass" modal>
<div style="text-align: center;">
<h2 style="color: var(--black);">Qortal ${translate("tabmenu.tm6")} ${translate("login.lp1")}</h2>
<hr>
</div>
<div style="text-align: center;">
<h3 style="color: var(--black);">${translate("login.lp2")}</h3>
<h4 style="color: var(--black);">${translate("login.lp3")}</h4>
</div>
<div style="display:flex;">
<mwc-icon style="padding: 10px; padding-left: 0; padding-top: 42px; color: var(--black);">password</mwc-icon>
<vaadin-password-field style="width: 100%;" label="${translate("login.password")}" id="autoLockPassword" autofocus></vaadin-password-field>
</div>
<div style="display:flex;">
<mwc-icon style="padding: 10px; padding-left: 0; padding-top: 42px; color: var(--black);">password</mwc-icon>
<vaadin-password-field style="width: 100%;" label="${translate("login.confirmpass")}" id="autoLockPasswordConfirm"></vaadin-password-field>
</div>
<div style="display: flex; justify-content: space-between;">
<mwc-button class="red" @click="${() => this.closewAutoSetScreenLockPass()}">${translate("login.lp4")}</mwc-button>
<mwc-button @click="${() => this.autoCheckPass()}">${translate("login.lp5")}</mwc-button>
</div>
</paper-dialog>
<paper-dialog class="setpass-wrapper" id="autoExtraConfirmPass" modal>
<div style="text-align: center;">
<h2 style="color: var(--black);">Qortal ${translate("tabmenu.tm6")} ${translate("login.lp1")}</h2>
<hr>
</div>
<div style="text-align: center;">
<h3 style="color: var(--black);">${translate("login.lessthen8")}</h3>
</div>
<div style="display: flex; justify-content: space-between;">
<mwc-button class="red" @click="${() => this.closAutoExtraConfirmPass()}">${translate("login.lp4")}</mwc-button>
<mwc-button @click="${() => this.setAutoNewScreenPass()}">${translate("login.lp5")}</mwc-button>
</div>
</paper-dialog>
<paper-dialog class="lock-wrapper" id="autoLockScreenActive" modal>
<div class="text-wrapper">
<span class="lock-title-white">${translate("tradepage.tchange46")}</span><br/>
<span class="lock-title-white">${translate("login.lp9")} </span>
<span class="lock-title-red">${translate("login.lp10")}</span>
</div>
<div style="display:flex; margin-top: 5px;">
<mwc-icon style="padding: 10px; padding-left: 0; padding-top: 42px; color: var(--black);">password</mwc-icon>
<vaadin-password-field style="width: 45%;" label="${translate("login.password")}" id="autoUnlockPassword" @keydown="${this.autoPassKeyListener}" autofocus>
<div slot="helper">
${this.autoHelperMessage}
</div>
</vaadin-password-field>
</div>
<div style="display: flex; margin-top: 35px;">
<mwc-button dense unelevated label="${translate("login.lp7")}" icon="lock_open" @click="${() => this.closeAutoLockScreenActive()}"></mwc-button>
</div>
</paper-dialog>
`
}
@@ -1977,6 +2105,45 @@ class TradeBotPortal extends LitElement {
this.changeTheme()
this.changeLanguage()
this.autoHelperMessage = this.renderAutoHelperPass()
this.autoSalt = ''
this.autoSalt = Base58.encode(window.parent.reduxStore.getState().app.wallet._addresses[0].keyPair.privateKey)
this.autoStorageData = ''
this.autoStorageData = window.parent.reduxStore.getState().app.selectedAddress.address
this.autoLockScreenPass = ''
this.autoLockScreenPass = 'autoLockScreenPass-' + this.autoStorageData
this.autoLockScreenSet = ''
this.autoLockScreenSet = 'autoLockScreenSet-' + this.autoStorageData
this.autoLockPass = ''
this.autoLockPass = encryptData(false, this.autoSalt)
this.autoLockSet = ''
this.autoLockSet = encryptData(false, this.autoSalt)
if (localStorage.getItem(this.autoLockScreenPass) === null && localStorage.getItem(this.autoLockScreenSet) === null) {
localStorage.setItem(this.autoLockScreenPass, this.autoLockPass)
localStorage.setItem(this.autoLockScreenSet, this.autoLockSet)
this.myAutoLockScreenPass = ''
this.myAutoLockScreenPass = decryptData(localStorage.getItem(this.autoLockScreenPass), this.autoSalt)
this.myAutoLockScreenSet = ''
this.myAutoLockScreenSet = decryptData(localStorage.getItem(this.autoLockScreenSet), this.autoSalt)
} else {
this.myAutoLockScreenPass = ''
this.myAutoLockScreenPass = decryptData(localStorage.getItem(this.autoLockScreenPass), this.autoSalt)
this.myAutoLockScreenSet = ''
this.myAutoLockScreenSet = decryptData(localStorage.getItem(this.autoLockScreenSet), this.autoSalt)
}
if (this.myAutoLockScreenSet === true) {
this.shadowRoot.getElementById('autoLockScreenActive').open()
}
this.updateWalletBalance()
this.fetchWalletAddress(this.selectedCoin)
@@ -2036,17 +2203,6 @@ class TradeBotPortal extends LitElement {
setTimeout(getQortArrrPrice, 300000)
}
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
this._textMenu(event)},
{ passive: true }
)
window.addEventListener('click', () => {
parentEpml.request('closeCopyTextMenu', null)},
{ passive: true }
)
window.addEventListener('storage', () => {
this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]")
this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]")
@@ -2063,8 +2219,12 @@ class TradeBotPortal extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
window.onkeyup = (e) => {
if (e.keyCode === 27) parentEpml.request('closeCopyTextMenu', null)
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
this.btcWallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet.address
@@ -2106,10 +2266,6 @@ class TradeBotPortal extends LitElement {
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async (value) => {
if (value === 'false' && window.getSelection().toString().length !== 0) this.clearSelection()
})
let coinSelectionMenu = this.shadowRoot.getElementById("coinSelectionMenu")
coinSelectionMenu.addEventListener('change', function () {
@@ -2127,6 +2283,137 @@ class TradeBotPortal extends LitElement {
this.arrrTradebook()
}
renderAutoLockButton() {
if (this.myAutoLockScreenPass === false && this.myAutoLockScreenSet === false) {
return html`
<div style="display: inline;">
<paper-icon-button style="padding-bottom: 12px;" icon="icons:lock-open" @click=${() => this.openAutoSetScreenLockPass()} title="${translate("login.lp11")}"></paper-icon-button>
</div>
`
} else if (this.myAutoLockScreenSet === false) {
return html`
<div style="display: inline;">
<paper-icon-button style="padding-bottom: 12px;" icon="icons:lock-open" @click=${() => this.setAutoLockQortal()} title="${translate("login.lp11")}"></paper-icon-button>
</div>
`
} else if (this.myAutoLockScreenSet === true) {
return html`
<div style="display: inline;">
<paper-icon-button style="padding-bottom: 12px;" icon="icons:lock" title="${translate("login.lp10")}"></paper-icon-button>
</div>
`
}
}
openAutoSetScreenLockPass() {
this.shadowRoot.getElementById('autoLockPassword').value = ''
this.shadowRoot.getElementById('autoLockPasswordConfirm').value = ''
this.shadowRoot.getElementById('setAutoLockScreenPass').open()
}
closewAutoSetScreenLockPass() {
this.shadowRoot.getElementById('setAutoLockScreenPass').close()
}
autoCheckPass() {
const autoPassword = this.shadowRoot.getElementById('autoLockPassword').value
const autoRePassword = this.shadowRoot.getElementById('autoLockPasswordConfirm').value
if (autoPassword === '') {
let snackbar1string = get("login.pleaseenter")
parentEpml.request('showSnackBar', `${snackbar1string}`)
return
}
if (autoPassword != autoRePassword) {
let snackbar2string = get("login.notmatch")
parentEpml.request('showSnackBar', `${snackbar2string}`)
return
}
if (autoPassword.length < 8) {
let snackbar3string = get("login.lessthen8")
parentEpml.request('showSnackBar', `${snackbar3string}`)
this.autoExtraConfirm()
}
if (autoPassword.length >= 8) {
this.setAutoNewScreenPass()
let snackbar4string = get("login.lp6")
parentEpml.request('showSnackBar', `${snackbar4string}`)
}
}
autoExtraConfirm() {
this.shadowRoot.getElementById('setAutoLockScreenPass').close()
this.shadowRoot.getElementById('autoExtraConfirmPass').open()
}
closAutoExtraConfirmPass() {
this.shadowRoot.getElementById('autoExtraConfirmPass').close()
this.shadowRoot.getElementById('autoLockPassword').value = ''
this.shadowRoot.getElementById('autoLockPasswordConfirm').value = ''
}
setAutoNewScreenPass() {
const autoRawPassword = this.shadowRoot.getElementById('autoLockPassword').value
const autoCryptPassword = encryptData(autoRawPassword, this.autoSalt)
localStorage.setItem(this.autoLockScreenPass, autoCryptPassword)
this.myAutoLockScreenPass = ''
this.myAutoLockScreenPass = decryptData(localStorage.getItem(this.autoLockScreenPass), this.autoSalt)
this.shadowRoot.getElementById('setAutoLockScreenPass').close()
this.shadowRoot.getElementById('autoExtraConfirmPass').close()
this.shadowRoot.getElementById('autoLockPassword').value = ''
this.shadowRoot.getElementById('autoLockPasswordConfirm').value = ''
}
setAutoLockQortal() {
this.autoHelperMessage = this.renderAutoHelperPass()
this.autoLockSet = ''
this.autoLockSet = encryptData(true, this.autoSalt)
localStorage.setItem(this.autoLockScreenSet, this.autoLockSet)
this.myAutoLockScreenSet = ''
this.myAutoLockScreenSet = decryptData(localStorage.getItem(this.autoLockScreenSet), this.autoSalt)
this.shadowRoot.getElementById('autoLockScreenActive').open()
}
autoPassKeyListener(e) {
if (e.key === 'Enter') {
this.closeAutoLockScreenActive()
}
}
async closeAutoLockScreenActive() {
const myAutoPass = decryptData(localStorage.getItem(this.autoLockScreenPass), this.autoSalt)
const autoCheckPass = this.shadowRoot.getElementById('autoUnlockPassword').value
const errDelay = ms => new Promise(res => setTimeout(res, ms))
if (autoCheckPass === myAutoPass) {
this.autoLockSet = ''
this.autoLockSet = encryptData(false, this.autoSalt)
localStorage.setItem(this.autoLockScreenSet, this.autoLockSet)
this.myAutoLockScreenSet = ''
this.myAutoLockScreenSet = decryptData(localStorage.getItem(this.autoLockScreenSet), this.autoSalt)
this.shadowRoot.getElementById('autoLockScreenActive').close()
this.shadowRoot.getElementById('autoUnlockPassword').value = ''
this.autoHelperMessage = this.renderAutoHelperPass()
} else {
this.shadowRoot.getElementById('autoUnlockPassword').value = ''
this.autoHelperMessage = this.renderAutoHelperErr()
await errDelay(3000)
this.autoHelperMessage = this.renderAutoHelperPass()
return
}
}
renderAutoHelperPass() {
return html`<span style="color: #fff; font-weight: bold; font-size: 13px; float: left;">${translate("login.pleaseenter")}</span>`
}
renderAutoHelperErr() {
return html`<span style="color: var(--mdc-theme-error); font-weight: bold; font-size: 13px; float: right;">${translate("login.lp8")}</span>`
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
this.theme = (checkTheme === 'dark') ? 'dark' : 'light'
@@ -2718,8 +3005,10 @@ class TradeBotPortal extends LitElement {
checkTradeBotValues() {
const checkTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value
const checkTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value
const checkTradeBotTotalInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value
const checkAmount = this.round(parseFloat(checkTradeBotAmountInput))
const checkPrice = this.round(parseFloat(checkTradeBotPriceInput))
const checkTotal = this.round(parseFloat(checkTradeBotTotalInput))
if (Number(checkAmount) === 0) {
let amountString = get("tradepage.tchange34")
@@ -2727,6 +3016,9 @@ class TradeBotPortal extends LitElement {
} else if (Number(checkPrice) === 0) {
let priceString = get("tradepage.tchange35")
parentEpml.request('showSnackBar', `${priceString}`)
} else if (Number(checkTotal) === 0) {
let totalString = get("tradepage.tchange35")
parentEpml.request('showSnackBar', `${totalString}`)
} else {
this.showAddToAutoBuyStore()
}
@@ -3280,6 +3572,7 @@ class TradeBotPortal extends LitElement {
} else {
const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value
const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value
const buyTradeBotTotalInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value
const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput))
const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance))
if (Number(myFunds) > Number(checkFunds)) {
@@ -3312,6 +3605,7 @@ class TradeBotPortal extends LitElement {
} else {
const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value
const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value
const buyTradeBotTotalInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value
const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput))
const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance))
if (Number(myFunds) > Number(checkFunds)) {
@@ -3331,6 +3625,7 @@ class TradeBotPortal extends LitElement {
} else {
const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value
const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value
const buyTradeBotTotalInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value
const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput))
const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance))
if (Number(myFunds) > Number(checkFunds)) {
@@ -3346,48 +3641,96 @@ class TradeBotPortal extends LitElement {
}
}
checkTradeBotTotalAmount(e) {
const targetAmount = e.target.value
const target = e.target
this.autoBuyWarning = false
if (targetAmount.length === 0) {
this.isValidAmount = false
this.autoBuyBtnDisable = true
this.autoBuyWarning = false
e.target.blur()
e.target.focus()
e.target.invalid = true
} else {
const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value
const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value
const buyTradeBotTotalInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value
const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput))
const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance))
if (Number(myFunds) > Number(checkFunds)) {
this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value = this.round(parseFloat(buyTradeBotTotalInput) / parseFloat(buyTradeBotPriceInput))
this.autoBuyBtnDisable = false
this.autoBuyWarning = false
} else {
this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value = this.round(parseFloat(buyTradeBotTotalInput) / parseFloat(buyTradeBotPriceInput))
this.autoBuyBtnDisable = true
this.autoBuyWarning = true
}
}
e.target.blur()
e.target.focus()
e.target.validityTransform = (newValue, nativeValidity) => {
if (newValue.includes('-') === true) {
this.autoBuyBtnDisable = true
this.autoBuyWarning = false
return {
valid: false,
}
} else if (!nativeValidity.valid) {
if (newValue.includes('.') === true) {
let myAmount = newValue.split('.')
if (myAmount[1].length > 8) {
this.autoBuyBtnDisable = true
this.autoBuyWarning = false
} else {
const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value
const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value
const buyTradeBotTotalInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value
const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput))
const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance))
if (Number(myFunds) > Number(checkFunds)) {
this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value = this.round(parseFloat(buyTradeBotTotalInput) / parseFloat(buyTradeBotPriceInput))
this.autoBuyBtnDisable = false
this.autoBuyWarning = false
} else {
this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value = this.round(parseFloat(buyTradeBotTotalInput) / parseFloat(buyTradeBotPriceInput))
this.autoBuyBtnDisable = true
this.autoBuyWarning = true
}
return {
valid: true,
}
}
}
} else {
const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value
const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value
const buyTradeBotTotalInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value
const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput))
const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance))
if (Number(myFunds) > Number(checkFunds)) {
this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value = this.round(parseFloat(buyTradeBotTotalInput) / parseFloat(buyTradeBotPriceInput))
this.autoBuyBtnDisable = false
this.autoBuyWarning = false
} else {
this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value = this.round(parseFloat(buyTradeBotTotalInput) / parseFloat(buyTradeBotPriceInput))
this.autoBuyBtnDisable = true
this.autoBuyWarning = true
}
}
}
}
getApiKey() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
let apiKey = myNode.apiKey;
return apiKey;
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
_textMenu(event) {
const getSelectedText = () => {
var text = ''
if (typeof window.getSelection != 'undefined') {
text = window.getSelection().toString()
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
text = this.shadowRoot.selection.createRange().text
}
return text
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText()
if (selectedText && typeof selectedText === 'string') {
let _eve = {
pageX: event.pageX,
pageY: event.pageY,
clientX: event.clientX,
clientY: event.clientY,
}
let textMenuObject = {
selectedText: selectedText,
eventObject: _eve,
isFrame: true,
}
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
clearTradeBotForm() {
this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value = this.initialAmount
this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value = this.initialAmount

View File

@@ -1,7 +1,10 @@
import { LitElement, html, css } from 'lit'
import { render } from 'lit/html.js'
import { Epml } from '../../../epml.js'
import isElectron from 'is-electron'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
import Base58 from '../../../../crypto/api/deps/Base58.js'
import { encryptData, decryptData } from '../../../../core/src/lockScreen.js'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
@@ -23,12 +26,14 @@ import '@polymer/paper-icon-button/paper-icon-button.js'
import '@polymer/paper-spinner/paper-spinner-lite.js'
import '@vaadin/grid'
import '@vaadin/grid/vaadin-grid-sorter'
import '@vaadin/password-field'
import chartsbtc from './charts/btc-charts.js'
import chartsltc from './charts/ltc-charts.js'
import chartsdoge from './charts/doge-charts.js'
import chartsdgb from './charts/dgb-charts.js'
import chartsrvn from './charts/rvn-charts.js'
import chartsarrr from './charts/arrr-charts.js'
import '../components/TraderInfoView.js'
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
@@ -76,13 +81,16 @@ class TradePortal extends LitElement {
dgbqort: { type: Number },
rvnqort: { type: Number },
arrrqort: { type: Number },
tradeInfoAccountName: { type: String },
tradeImageUrl: { type: String },
tradeAddressResult: { type: Array },
displayTradeAddress: { type: String },
displayTradeLevel: { type: String },
displayTradeBalance: { type: String },
qortRatio: {type: Number}
qortRatio: {type: Number},
tradeSalt: { type: String },
tradeStorageData: { type: String },
tradeLockScreenPass: { type: String },
tradeLockScreenSet: { type: String },
tradeLockPass: { type: String },
tradeLockSet: { type: String },
myTradeLockScreenPass: { type: String },
myTradeLockScreenSet: { type: String },
tradeHelperMessage: { type: String }
}
}
@@ -92,17 +100,17 @@ class TradePortal extends LitElement {
--mdc-theme-primary: rgb(3, 169, 244);
--mdc-theme-secondary: var(--mdc-theme-primary);
--mdc-theme-error: rgb(255, 89, 89);
--mdc-text-field-outlined-idle-border-color: var(--txtfieldborder);
--mdc-text-field-outlined-idle-border-color: var(--txtfieldborder);
--mdc-text-field-outlined-hover-border-color: var(--txtfieldhoverborder);
--mdc-text-field-label-ink-color: var(--black);
--mdc-text-field-ink-color: var(--black);
--mdc-select-outlined-idle-border-color: var(--txtfieldborder);
--mdc-select-outlined-idle-border-color: var(--txtfieldborder);
--mdc-select-outlined-hover-border-color: var(--txtfieldhoverborder);
--mdc-select-label-ink-color: var(--black);
--mdc-select-ink-color: var(--black);
--mdc-theme-surface: var(--white);
--mdc-dialog-content-ink-color: var(--black);
--mdc-dialog-shape-radius: 25px;
--mdc-dialog-shape-radius: 25px;
--paper-input-container-focus-color: var(--mdc-theme-primary);
--lumo-primary-text-color: rgb(0, 167, 245);
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
@@ -116,17 +124,27 @@ class TradePortal extends LitElement {
--_lumo-grid-secondary-border-color: var(--border2);
}
.myhover vaadin-grid::part(first-column-cell):hover {
background-color: var(--black);
color: var(--white);
.myhover vaadin-grid-cell-content {
cursor: pointer;
}
.myfocused vaadin-grid::part(focused-cell) {
background-color: var(--black);
color: var(--white);
.myhover vaadin-grid::part(selected-row) {
color: green;
cursor: pointer;
}
vaadin-grid::part(selected-row) {
background-color: var(--black);
color: var(--white);
.myhover vaadin-grid::part(focused-selected-row) {
color: green;
cursor: pointer;
}
.myhover vaadin-grid::part(cell):hover {
cursor: pointer;
}
.myhover vaadin-grid::part(row):hover {
color: green;
cursor: pointer;
}
.myhover vaadin-grid::part(selected-row-cell) {
color: green;
cursor: pointer;
}
paper-spinner-lite {
height: 30px;
@@ -565,10 +583,10 @@ class TradePortal extends LitElement {
}
}
paper-dialog.info {
width: 75%;
width: 100%;
max-width: 75vw;
height: 35%;
max-height: 35vh;
height: 100%;
max-height: 50vh;
background-color: var(--white);
color: var(--black);
border: 1px solid var(--black);
@@ -589,41 +607,97 @@ class TradePortal extends LitElement {
cursor: pointer;
opacity: .6;
}
@media (min-width: 701px) {
* {
}
#trade-portal {}
#first-trade-section {
display: grid;
grid-template-columns:1fr 1fr 2fr;
grid-auto-rows: max(450px);
column-gap: 0.5em;
row-gap: 0.4em;
justify-items: stretch;
align-items: stretch;
margin-bottom: 10px;
}
#second-trade-section {
display: grid;
grid-template-columns: 2fr 1fr;
grid-auto-rows: max(450px);
column-gap: 0.5em;
row-gap: 0.4em;
justify-items: stretch;
align-items: stretch;
margin-bottom: 10px;
}
#third-trade-section {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-auto-rows: max(200px);
column-gap: 0.5em;
row-gap: 0.4em;
justify-items: stretch;
align-items: stretch;
margin-bottom: 10px;
}
}
.setpass-wrapper {
width: 100%;
min-width: 400px;
max-width: 450px;
text-align: center;
background: var(--white);
border: 1px solid var(--black);
border-radius: 15px;
padding: 10px 10px 0px;
box-shadow: 0px 10px 15px rgba(0, 0, 0, 0.1);
}
.lock-wrapper {
width: 100%;
height: 100%;
min-width: 600px;
max-width: 600px;
min-height: 400px;
max-height: 400px;
text-align: center;
background: url("/img/qortal-lock.jpg");
border: 1px solid var(--black);
border-radius: 25px;
padding: 10px 10px 0px;
}
.text-wrapper {
width: 100%;
height: 100%;
min-width: 280px;
max-width: 280px;
min-height: 64px;
max-height: 64px;
text-align: center;
margin-left: 35px;
margin-top: 125px;
overflow: hidden;
}
.lock-title-white {
font-family: 'magistralbold';
font-weight: 700;
font-size: 26px;
line-height: 32px;
color: #ffffff;
}
.lock-title-red {
font-family: 'magistralbold';
font-weight: 700;
font-size: 26px;
line-height: 32px;
color: #df3636;
}
@media (min-width: 701px) {
* {
}
#trade-portal {}
#first-trade-section {
display: grid;
grid-template-columns:1fr 1fr 2fr;
grid-auto-rows: max(450px);
column-gap: 0.5em;
row-gap: 0.4em;
justify-items: stretch;
align-items: stretch;
margin-bottom: 10px;
}
#second-trade-section {
display: grid;
grid-template-columns: 2fr 1fr;
grid-auto-rows: max(450px);
column-gap: 0.5em;
row-gap: 0.4em;
justify-items: stretch;
align-items: stretch;
margin-bottom: 10px;
}
#third-trade-section {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-auto-rows: max(200px);
column-gap: 0.5em;
row-gap: 0.4em;
justify-items: stretch;
align-items: stretch;
margin-bottom: 10px;
}
}
`
}
@@ -821,6 +895,15 @@ class TradePortal extends LitElement {
this.displayTradeAddress = ''
this.displayTradeLevel = ''
this.displayTradeBalance = ''
this.tradeSalt = ''
this.tradeStorageData = ''
this.tradeLockScreenPass = ''
this.tradeLockScreenSet = ''
this.tradeLockPass = ''
this.tradeLockSet = ''
this.myTradeLockScreenPass = ''
this.myTradeLockScreenSet = ''
this.tradeHelperMessage = ''
}
historicTradesTemplate() {
@@ -860,7 +943,7 @@ class TradePortal extends LitElement {
openTradesTemplate() {
return html`
<div class="open-trades myhover myfocused">
<div class="open-trades myhover">
<div class="box">
<header><span>${translate("tradepage.tchange5")}</span></header>
<div class="border-wrapper">
@@ -889,7 +972,7 @@ class TradePortal extends LitElement {
header="${translate("tradepage.tchange9")} (${this.listedCoins.get(this.selectedCoin).coinCode})"
id="priceColumn"
.renderer=${(root, column, data) => {
render(html`<span @click="${() => this.fillBuyForm(data)}">${this.round(data.item.price)}</span>`, root)
render(html`<span style="cursor: pointer;" @click="${() => this.fillBuyForm(data)}">${this.round(data.item.price)}</span>`, root)
}}
>
</vaadin-grid-column>
@@ -899,7 +982,7 @@ class TradePortal extends LitElement {
header="${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})"
id="foreignAmountColumn"
.renderer=${(root, column, data) => {
render(html`<span @click="${() => this.fillBuyForm(data)}">${data.item.foreignAmount}</span>`, root)
render(html`<span style="cursor: pointer;" @click="${() => this.fillBuyForm(data)}">${data.item.foreignAmount}</span>`, root)
}}
>
</vaadin-grid-column>
@@ -909,7 +992,7 @@ class TradePortal extends LitElement {
header="${translate("tradepage.tchange13")}"
id="qortalCreatorColumn"
.renderer=${(root, column, data) => {
render(html`<span @click="${() => this.fillBuyForm(data)}">${data.item.qortalCreator}</span>`, root)
render(html`<span style="cursor: pointer;" @click="${() => this.fillBuyForm(data)}">${data.item.qortalCreator}</span>`, root)
}}
>
</vaadin-grid-column>
@@ -918,7 +1001,7 @@ class TradePortal extends LitElement {
resizable
header="${translate("explorerpage.exp7")}"
.renderer=${(root, column, data) => {
render(html`<span @click="${() => this.getAllForAddress(data.item.qortalCreator)}"><mwc-icon class="btn-info">info</mwc-icon></span>`, root)
render(html`<span style="cursor: pointer;" @click="${() => this.requestTraderInfo(data.item.qortalCreator)}"><mwc-icon class="btn-info">info</mwc-icon></span>`, root)
}}
>
</vaadin-grid-column>
@@ -1215,13 +1298,16 @@ class TradePortal extends LitElement {
<mwc-list-item value="RAVENCOIN"><span class="coinName rvn" style="color: var(--black);">QORT / RVN</span></mwc-list-item>
<mwc-list-item value="PIRATECHAIN"><span class="coinName arrr" style="color: var(--black);">QORT / ARRR</span></mwc-list-item>
</mwc-select>
<div style="padding-left: 20px; padding-top: 5px;">
<mwc-fab mini icon="info" title="${translate("info.inf1")}" @click=${() => this.shadowRoot.getElementById('tradeInfoDialog').open()}></mwc-fab>
</div>
<div style="padding-left: 20px; padding-top: 15px;">
${this.chartShowCoin()}
</div>
<div style="padding-left: 20px; padding-top: 5px;">
<mwc-fab mini icon="info" title="${translate("info.inf1")}" @click=${() => this.shadowRoot.getElementById('tradeInfoDialog').open()}></mwc-fab>
</div>
<div style="padding-left: 20px; padding-top: 15px;">
${this.chartShowCoin()}
</div>
<div style="padding-left: 10px; padding-top: 12px; color: var(--black);">
${this.renderTradeLockButton()}
</div>
</div>
<div id="trade-portal">
<div id="first-trade-section">
@@ -1261,30 +1347,72 @@ class TradePortal extends LitElement {
<mwc-button slot="primaryAction" dialogAction="cancel" class="cancel">${translate("general.close")}</mwc-button>
</mwc-dialog>
<mwc-dialog style="background: var(--white);" id="sellerDialog">
<div class="card-container">
<span class="level">${translate("mintingpage.mchange27")} ${this.displayTradeLevel}</span>
${this.tradeFounderBadge()}
${this.tradeAvatarImage()}
<h2>${this.tradeInfoAccountName}</h2>
<h4>${this.displayTradeAddress}</h4>
<p>${translate("explorerpage.exp2")}: ${this.displayTradeBalance} QORT</p>
<paper-dialog id="tradeInfoDialog" class="info" modal>
<div class="actions">
<h3></h3>
<mwc-icon class="close-icon" @click=${() => this.shadowRoot.getElementById('tradeInfoDialog').close()} title="${translate("info.inf2")}">highlight_off</mwc-icon>
</div>
<mwc-button slot="primaryAction" dialogAction="cancel" class="cancel">${translate("general.close")}</mwc-button>
</mwc-dialog>
<paper-dialog id="tradeInfoDialog" class="info" modal>
<div class="actions">
<h3></h3>
<mwc-icon class="close-icon" @click=${() => this.shadowRoot.getElementById('tradeInfoDialog').close()} title="${translate("info.inf2")}">highlight_off</mwc-icon>
</div>
<div class="container">
<h1 style="color: #03a9f4; text-align: center;">${translate("info.inf1")}</h1>
<h1 style="text-align: center;">${translate("info.inf3")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("info.inf4")}</h1>
<h1 style="text-align: center;">${translate("info.inf5")} ${this.listedCoins.get(this.selectedCoin).coinCode}</h1>
<h1 style="text-align: center;">${translate("info.inf6")}</h1>
</div>
</paper-dialog>
<div class="container">
<h1 style="color: #03a9f4; text-align: center;">${translate("info.inf1")}</h1>
<h2 style="text-align: center;">${translate("info.inf3")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("info.inf4")}</h2>
<h2 style="text-align: center;">${translate("info.inf5")} ${this.listedCoins.get(this.selectedCoin).coinCode}</h2>
<h2 style="text-align: center;">${translate("info.inf6")}</h2>
</div>
</paper-dialog>
<paper-dialog class="setpass-wrapper" id="setTradeLockScreenPass" modal>
<div style="text-align: center;">
<h2 style="color: var(--black);">Qortal ${translate("tabmenu.tm4")} ${translate("login.lp1")}</h2>
<hr>
</div>
<div style="text-align: center;">
<h3 style="color: var(--black);">${translate("login.lp2")}</h3>
<h4 style="color: var(--black);">${translate("login.lp3")}</h4>
</div>
<div style="display:flex;">
<mwc-icon style="padding: 10px; padding-left: 0; padding-top: 42px; color: var(--black);">password</mwc-icon>
<vaadin-password-field style="width: 100%;" label="${translate("login.password")}" id="tradeLockPassword" autofocus></vaadin-password-field>
</div>
<div style="display:flex;">
<mwc-icon style="padding: 10px; padding-left: 0; padding-top: 42px; color: var(--black);">password</mwc-icon>
<vaadin-password-field style="width: 100%;" label="${translate("login.confirmpass")}" id="tradeLockPasswordConfirm"></vaadin-password-field>
</div>
<div style="display: flex; justify-content: space-between;">
<mwc-button class="red" @click="${() => this.closewTradeSetScreenLockPass()}">${translate("login.lp4")}</mwc-button>
<mwc-button @click="${() => this.tradeCheckPass()}">${translate("login.lp5")}</mwc-button>
</div>
</paper-dialog>
<paper-dialog class="setpass-wrapper" id="tradeExtraConfirmPass" modal>
<div style="text-align: center;">
<h2 style="color: var(--black);">Qortal ${translate("tabmenu.tm4")} ${translate("login.lp1")}</h2>
<hr>
</div>
<div style="text-align: center;">
<h3 style="color: var(--black);">${translate("login.lessthen8")}</h3>
</div>
<div style="display: flex; justify-content: space-between;">
<mwc-button class="red" @click="${() => this.closTradeExtraConfirmPass()}">${translate("login.lp4")}</mwc-button>
<mwc-button @click="${() => this.setTradeNewScreenPass()}">${translate("login.lp5")}</mwc-button>
</div>
</paper-dialog>
<paper-dialog class="lock-wrapper" id="tradeLockScreenActive" modal>
<div class="text-wrapper">
<span class="lock-title-white">${translate("sidemenu.tradeportal")}</span><br/>
<span class="lock-title-white">${translate("login.lp9")} </span>
<span class="lock-title-red">${translate("login.lp10")}</span>
</div>
<div style="display:flex; margin-top: 5px;">
<mwc-icon style="padding: 10px; padding-left: 0; padding-top: 42px; color: var(--black);">password</mwc-icon>
<vaadin-password-field style="width: 45%;" label="${translate("login.password")}" id="tradeUnlockPassword" @keydown="${this.tradePassKeyListener}" autofocus>
<div slot="helper">
${this.tradeHelperMessage}
</div>
</vaadin-password-field>
</div>
<div style="display: flex; margin-top: 35px;">
<mwc-button dense unelevated label="${translate("login.lp7")}" icon="lock_open" @click="${() => this.closeTradeLockScreenActive()}"></mwc-button>
</div>
</paper-dialog>
<trader-info-view></trader-info-view>
`
}
@@ -1294,6 +1422,45 @@ class TradePortal extends LitElement {
this.changeTheme()
this.changeLanguage()
this.tradeHelperMessage = this.renderTradeHelperPass()
this.tradeSalt = ''
this.tradeSalt = Base58.encode(window.parent.reduxStore.getState().app.wallet._addresses[0].keyPair.privateKey)
this.tradeStorageData = ''
this.tradeStorageData = window.parent.reduxStore.getState().app.selectedAddress.address
this.tradeLockScreenPass = ''
this.tradeLockScreenPass = 'tradeLockScreenPass-' + this.tradeStorageData
this.tradeLockScreenSet = ''
this.tradeLockScreenSet = 'tradeLockScreenSet-' + this.tradeStorageData
this.tradeLockPass = ''
this.tradeLockPass = encryptData(false, this.tradeSalt)
this.tradeLockSet = ''
this.tradeLockSet = encryptData(false, this.tradeSalt)
if (localStorage.getItem(this.tradeLockScreenPass) === null && localStorage.getItem(this.tradeLockScreenSet) === null) {
localStorage.setItem(this.tradeLockScreenPass, this.tradeLockPass)
localStorage.setItem(this.tradeLockScreenSet, this.tradeLockSet)
this.myTradeLockScreenPass = ''
this.myTradeLockScreenPass = decryptData(localStorage.getItem(this.tradeLockScreenPass), this.tradeSalt)
this.myTradeLockScreenSet = ''
this.myTradeLockScreenSet = decryptData(localStorage.getItem(this.tradeLockScreenSet), this.tradeSalt)
} else {
this.myTradeLockScreenPass = ''
this.myTradeLockScreenPass = decryptData(localStorage.getItem(this.tradeLockScreenPass), this.tradeSalt)
this.myTradeLockScreenSet = ''
this.myTradeLockScreenSet = decryptData(localStorage.getItem(this.tradeLockScreenSet), this.tradeSalt)
}
if (this.myTradeLockScreenSet === true) {
this.shadowRoot.getElementById('tradeLockScreenActive').open()
}
this.updateWalletBalance()
this.fetchWalletAddress(this.selectedCoin)
@@ -1378,17 +1545,6 @@ class TradePortal extends LitElement {
setTimeout(getQortArrrPrice, 300000)
}
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
this._textMenu(event)},
{ passive: true }
)
window.addEventListener('click', () => {
parentEpml.request('closeCopyTextMenu', null)},
{ passive: true }
)
window.addEventListener('storage', () => {
const checkLanguage = localStorage.getItem('qortalLanguage')
const checkTheme = localStorage.getItem('qortalTheme')
@@ -1399,8 +1555,12 @@ class TradePortal extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme)
})
window.onkeyup = (e) => {
if (e.keyCode === 27) parentEpml.request('closeCopyTextMenu', null)
if (!isElectron()) {
} else {
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
window.parent.electronAPI.showMyMenu()
})
}
this.btcWallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet.address
@@ -1443,10 +1603,6 @@ class TradePortal extends LitElement {
this.config = JSON.parse(c)
})
parentEpml.subscribe('copy_menu_switch', async (value) => {
if (value === 'false' && window.getSelection().toString().length !== 0) this.clearSelection()
})
let coinSelectionMenu = this.shadowRoot.getElementById("coinSelectionMenu")
coinSelectionMenu.addEventListener('change', function () {
@@ -1460,6 +1616,143 @@ class TradePortal extends LitElement {
setTimeout(() => this.shadowRoot.querySelector('[slot="vaadin-grid-cell-content-3"]').setAttribute('title', 'Last Seen'), 3000)
}
renderTradeLockButton() {
if (this.myTradeLockScreenPass === false && this.myTradeLockScreenSet === false) {
return html`
<div style="display: inline;">
<paper-icon-button style="padding-bottom: 12px;" icon="icons:lock-open" @click=${() => this.openTradeSetScreenLockPass()} title="${translate("login.lp11")}"></paper-icon-button>
</div>
`
} else if (this.myTradeLockScreenSet === false) {
return html`
<div style="display: inline;">
<paper-icon-button style="padding-bottom: 12px;" icon="icons:lock-open" @click=${() => this.setTradeLockQortal()} title="${translate("login.lp11")}"></paper-icon-button>
</div>
`
} else if (this.myTradeLockScreenSet === true) {
return html`
<div style="display: inline;">
<paper-icon-button style="padding-bottom: 12px;" icon="icons:lock" title="${translate("login.lp10")}"></paper-icon-button>
</div>
`
}
}
openTradeSetScreenLockPass() {
this.shadowRoot.getElementById('tradeLockPassword').value = ''
this.shadowRoot.getElementById('tradeLockPasswordConfirm').value = ''
this.shadowRoot.getElementById('setTradeLockScreenPass').open()
}
closewTradeSetScreenLockPass() {
this.shadowRoot.getElementById('setTradeLockScreenPass').close()
}
tradeCheckPass() {
const tradePassword = this.shadowRoot.getElementById('tradeLockPassword').value
const tradeRePassword = this.shadowRoot.getElementById('tradeLockPasswordConfirm').value
if (tradePassword === '') {
let snackbar1string = get("login.pleaseenter")
parentEpml.request('showSnackBar', `${snackbar1string}`)
return
}
if (tradePassword != tradeRePassword) {
let snackbar2string = get("login.notmatch")
parentEpml.request('showSnackBar', `${snackbar2string}`)
return
}
if (tradePassword.length < 8) {
let snackbar3string = get("login.lessthen8")
parentEpml.request('showSnackBar', `${snackbar3string}`)
this.tradeExtraConfirm()
}
if (tradePassword.length >= 8) {
this.setTradeNewScreenPass()
let snackbar4string = get("login.lp6")
parentEpml.request('showSnackBar', `${snackbar4string}`)
}
}
tradeExtraConfirm() {
this.shadowRoot.getElementById('setTradeLockScreenPass').close()
this.shadowRoot.getElementById('tradeExtraConfirmPass').open()
}
closTradeExtraConfirmPass() {
this.shadowRoot.getElementById('tradeExtraConfirmPass').close()
this.shadowRoot.getElementById('tradeLockPassword').value = ''
this.shadowRoot.getElementById('tradeLockPasswordConfirm').value = ''
}
setTradeNewScreenPass() {
const tradeRawPassword = this.shadowRoot.getElementById('tradeLockPassword').value
const tradeCryptPassword = encryptData(tradeRawPassword, this.tradeSalt)
localStorage.setItem(this.tradeLockScreenPass, tradeCryptPassword)
this.myTradeLockScreenPass = ''
this.myTradeLockScreenPass = decryptData(localStorage.getItem(this.tradeLockScreenPass), this.tradeSalt)
this.shadowRoot.getElementById('setTradeLockScreenPass').close()
this.shadowRoot.getElementById('tradeExtraConfirmPass').close()
this.shadowRoot.getElementById('tradeLockPassword').value = ''
this.shadowRoot.getElementById('tradeLockPasswordConfirm').value = ''
}
setTradeLockQortal() {
this.tradeHelperMessage = this.renderTradeHelperPass()
this.tradeLockSet = ''
this.tradeLockSet = encryptData(true, this.tradeSalt)
localStorage.setItem(this.tradeLockScreenSet, this.tradeLockSet)
this.myTradeLockScreenSet = ''
this.myTradeLockScreenSet = decryptData(localStorage.getItem(this.tradeLockScreenSet), this.tradeSalt)
this.shadowRoot.getElementById('tradeLockScreenActive').open()
}
tradePassKeyListener(e) {
if (e.key === 'Enter') {
this.closeTradeLockScreenActive()
}
}
async closeTradeLockScreenActive() {
const myTradePass = decryptData(localStorage.getItem(this.tradeLockScreenPass), this.tradeSalt)
const tradeCheckPass = this.shadowRoot.getElementById('tradeUnlockPassword').value
const errDelay = ms => new Promise(res => setTimeout(res, ms))
if (tradeCheckPass === myTradePass) {
this.tradeLockSet = ''
this.tradeLockSet = encryptData(false, this.tradeSalt)
localStorage.setItem(this.tradeLockScreenSet, this.tradeLockSet)
this.myTradeLockScreenSet = ''
this.myTradeLockScreenSet = decryptData(localStorage.getItem(this.tradeLockScreenSet), this.tradeSalt)
this.shadowRoot.getElementById('tradeLockScreenActive').close()
this.shadowRoot.getElementById('tradeUnlockPassword').value = ''
this.tradeHelperMessage = this.renderTradeHelperPass()
} else {
this.shadowRoot.getElementById('tradeUnlockPassword').value = ''
this.tradeHelperMessage = this.renderTradeHelperErr()
await errDelay(3000)
this.tradeHelperMessage = this.renderTradeHelperPass()
return
}
}
renderTradeHelperPass() {
return html`<span style="color: #fff; font-weight: bold; font-size: 13px; float: left;">${translate("login.pleaseenter")}</span>`
}
renderTradeHelperErr() {
return html`<span style="color: var(--mdc-theme-error); font-weight: bold; font-size: 13px; float: right;">${translate("login.lp8")}</span>`
}
requestTraderInfo(traderAddress) {
let getAddress = traderAddress
const theInfoView = this.shadowRoot.querySelector('trader-info-view')
theInfoView.openTraderInfo(getAddress)
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
this.theme = (checkTheme === 'dark') ? 'dark' : 'light'
@@ -1737,73 +2030,6 @@ class TradePortal extends LitElement {
}
async getAllForAddress(tradeAddress) {
await this.getAddressTradeInfo(tradeAddress)
await this.getAddressTradeAvatar(tradeAddress)
await this.getAddressTradeBalance(tradeAddress)
this.displayTradeAddress = this.tradeAddressResult.address
this.displayTradeLevel = this.tradeAddressResult.level
this.shadowRoot.querySelector('#sellerDialog').show()
}
async getAddressTradeInfo(tradeInfoAddress) {
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 tradeInfoAddressUrl = `${nodeUrl}/addresses/${tradeInfoAddress}`
const qortalTradeAddressInfo = await fetch(tradeInfoAddressUrl).then(response => {
return response.json()
})
this.tradeAddressResult = qortalTradeAddressInfo
}
async getAddressTradeAvatar(tradeAvatarAddress) {
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 tradeNameUrl = `${nodeUrl}/names/address/${tradeAvatarAddress}?limit=0&reverse=true`
await fetch(tradeNameUrl).then(res => {
return res.json()
}).then(jsonRes => {
if(jsonRes.length) {
jsonRes.map (item => {
this.tradeInfoAccountName = item.name
this.tradeImageName = item.name
})
} else {
this.tradeInfoAccountName = "No registered name"
this.tradeImageName = tradeAvatarAddress
}
})
const myTradeImageUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${this.tradeImageName}/qortal_avatar?async=true&apiKey=${this.getApiKey()}`
this.tradeImageUrl = myTradeImageUrl
}
async getAddressTradeBalance(tradeBalanceAddress) {
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 tradeBalanceAddressUrl = `${nodeUrl}/addresses/balance/${tradeBalanceAddress}`
const qortalTradeBalanceInfo = await fetch(tradeBalanceAddressUrl).then(res => {
return res.json()
})
this.displayTradeBalance = qortalTradeBalanceInfo
}
tradeAvatarImage() {
return html`<img class="round" src="${this.tradeImageUrl}" onerror="this.src='/img/incognito.png';" />`
}
tradeFounderBadge() {
if (this.tradeAddressResult.flags === 1) {
return html`<span class="founder">${translate("explorerpage.exp6")}</span>`
} else {
return html``
}
}
processOfferingTrade(offer) {
try {
if(this.listedCoins.get(offer.foreignBlockchain).name!='') {
@@ -2790,42 +3016,6 @@ class TradePortal extends LitElement {
return apiKey;
}
clearSelection() {
window.getSelection().removeAllRanges()
window.parent.getSelection().removeAllRanges()
}
_textMenu(event) {
const getSelectedText = () => {
var text = ''
if (typeof window.getSelection != 'undefined') {
text = window.getSelection().toString()
} else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
text = this.shadowRoot.selection.createRange().text
}
return text
}
const checkSelectedTextAndShowMenu = () => {
let selectedText = getSelectedText()
if (selectedText && typeof selectedText === 'string') {
let _eve = {
pageX: event.pageX,
pageY: event.pageY,
clientX: event.clientX,
clientY: event.clientY,
}
let textMenuObject = {
selectedText: selectedText,
eventObject: _eve,
isFrame: true,
}
parentEpml.request('openCopyTextMenu', textMenuObject)
}
}
checkSelectedTextAndShowMenu()
}
clearBuyForm() {
this.shadowRoot.getElementById('buyAmountInput').value = this.initialAmount
this.shadowRoot.getElementById('buyPriceInput').value = this.initialAmount

File diff suppressed because it is too large Load Diff