Merge branch 'master' into qdn-metadata

# Conflicts:
#	qortal-ui-plugins/plugins/core/qdn/publish/publish.src.js
#	qortal-ui-plugins/plugins/core/qdn/websites.src.js
This commit is contained in:
CalDescent 2022-03-08 09:16:46 +00:00
commit 0a1e67fffb
51 changed files with 1545 additions and 899 deletions

View File

@ -1,7 +1,7 @@
# Qortal Project UI
[![License](https://img.shields.io/badge/license-GPL--3.0-blue)](https://opensource.org/licenses/GPL-3.0)
<a href="https://discord.com/invite/54UyhB7"><img src="https://badgen.net/badge/Discord/join-us/7289DA" alt="Discord"></a>
[![Qortal Discord Invite](https://img.shields.io/discord/745037351163527189?color=%237289DA&label=chat&logo=discord&logoColor=white)](https://discord.com/invite/54UyhB7)
Decentralizing The World

View File

@ -0,0 +1,4 @@
import { html } from 'lit'
export const svgSun = html`<svg height="64px" style="shape-rendering:geometricPrecision;text-rendering:geometricPrecision;image-rendering:optimizeQuality;fill-rule:evenodd;clip-rule:evenodd;width: 32px;" version="1.1" viewBox="0 0 64 64" width="64px" xml:space="preserve"><defs><style type="text/css">.str0 {stroke:#FFC106;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:22.9256} .fil1 {fill:none} .fil0 {fill:#FFC106}</style></defs><g id="Layer_x0020_1"><g id="_866321920"><circle class="fil0" r="22.97" transform="matrix(0.543121 0.145529 -0.145529 0.543121 32.0002 31.9993)"/><path class="fil1 str0" d="M32 12.4c0,1.52 0,2 0,2m-9.8 0.63c0.76,1.32 1,1.73 1,1.73m-8.17 5.44c1.32,0.76 1.73,1 1.73,1m-4.36 8.8c1.53,0 2,0 2,0m0.63 9.8c1.32,-0.76 1.73,-1 1.73,-1m5.44 8.17c0.76,-1.32 1,-1.73 1,-1.73m8.8 4.36c0,-1.53 0,-2 0,-2m9.8 -0.63c-0.76,-1.32 -1,-1.73 -1,-1.73m8.17 -5.44c-1.32,-0.76 -1.73,-1 -1.73,-1m4.36 -8.8c-1.53,0 -2,0 -2,0m-0.63 -9.8c-1.32,0.76 -1.73,1 -1.73,1m-5.44 -8.17c-0.76,1.32 -1,1.73 -1,1.73"/></g></g></svg>`;
export const svgMoon = html `<svg height="32px" style="enable-background:new 0 0 32 32;" version="1.1" viewBox="0 0 32 32" width="32px" xml:space="preserve"><g id="Layer_1"/><g id="moon_x5F_fill"><g><path d="M24.633,22.184c-8.188,0-14.82-6.637-14.82-14.82c0-2.695,0.773-5.188,2.031-7.363 C5.02,1.969,0,8.188,0,15.645C0,24.676,7.32,32,16.352,32c7.457,0,13.68-5.023,15.648-11.844 C29.82,21.41,27.328,22.184,24.633,22.184z" style="fill:#4E4E50;"/></g></g></svg>`;

View File

@ -0,0 +1,45 @@
html {
--white: #ffffff;
--black: #080808;
--gray: #c8c8c8;
--graylight: #bbbbbb;
--plugback: #ffffff;
--border: #d0d6de;
--border2: #dde2e8;
--copybutton: #707584;
--sectxt: #576374;
--vdicon: #707b8a;
--tradehead: #6a6c75;
--tradeborder: #666666;
--tradehave: #555555;
--txtfieldborder: #666666;
--txtfieldhoverborder: #00000;
--relaynodetxt: #646464;
--menuhover: #eeeeee;
--menuactive: #ebebeb;
--mainmenutext:#080808;
--mainmenutexthover:#080808;
}
html[theme="dark"] {
--white: #0f1a2e;
--black: #c9d2d9;
--gray: #d8d8d8;
--graylight: #0b305e;
--plugback: #0f1a2e;
--border: #0b305e;
--border2: #0b305e;
--copybutton: #d0d6de;
--sectxt: #bbc3cd;
--vdicon: #d0d6de;
--tradehead: #008fd5;
--tradeborder: #0b305e;
--tradehave: #dddddd;
--txtfieldborder: #0b305e;
--txtfieldhoverborder: #ffffff;
--relaynodetxt: #d4d4d4;
--menuhover: #008fd5;
--menuactive: #008fd5;
--mainmenutext:#008fd5;
--mainmenutexthover:#0f1a2e;
}

View File

@ -19,7 +19,7 @@
"dependencies": {
"@hapi/hapi": "^20.2.1",
"@hapi/inert": "^6.0.5",
"sass": "^1.49.8"
"sass": "^1.49.9"
},
"devDependencies": {
"@babel/core": "^7.17.5",
@ -55,17 +55,17 @@
"@polymer/paper-tooltip": "^3.0.1",
"@rollup/plugin-alias": "^3.1.9",
"@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-commonjs": "^21.0.2",
"@rollup/plugin-node-resolve": "^13.1.3",
"@rollup/plugin-replace": "^4.0.0",
"@vaadin/grid": "^22.0.5",
"@vaadin/password-field": "^22.0.5",
"@vaadin/grid": "^23.0.1",
"@vaadin/password-field": "^23.0.1",
"asmcrypto.js": "^2.3.2",
"bcryptjs": "^2.4.3",
"epml": "^0.3.3",
"file-saver": "^2.0.5",
"lit": "^2.2.0",
"postcss": "^8.4.6",
"postcss": "^8.4.7",
"pwa-helpers": "^0.9.1",
"random-sentence-generator": "^0.0.8",
"redux": "^4.1.2",

View File

@ -21,9 +21,9 @@
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon/favicon-16x16.png">
<link rel="manifest" href="/img/favicon/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileColor" content="var(--white)">
<meta name="msapplication-TileImage" content="/img/favicon/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<meta name="theme-color" content="var(--white)">
<style>
html {
@ -55,12 +55,13 @@
body {
margin: 0;
padding: 0;
background: #eee;
background: background: var(--plugback);
overflow: hidden;
}
</style>
<link rel="stylesheet" href="/build/styles.bundle.css">
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<title>Qortal</title>

View File

@ -27,10 +27,12 @@ class AppInfo extends connect(store)(LitElement) {
.normal {
--mdc-theme-primary: rgb(3, 169, 244);
}
.normal-button {
--mdc-theme-primary: rgb(3, 169, 244);
--mdc-theme-on-primary: white;
}
mwc-button.normal-button {
--mdc-theme-primary: rgb(3, 169, 244);
--mdc-theme-on-primary: white;
@ -38,10 +40,12 @@ class AppInfo extends connect(store)(LitElement) {
.test-net {
--mdc-theme-primary: black;
}
.test-net-button {
--mdc-theme-primary: black;
--mdc-theme-on-primary: white;
}
mwc-button.test-net-button {
--mdc-theme-primary: black;
--mdc-theme-on-primary: white;
@ -49,7 +53,8 @@ class AppInfo extends connect(store)(LitElement) {
#profileInMenu {
flex: 0 0 100px;
padding:12px;
border-top: 1px solid #eee;
border-top: 1px solid var(--border);
background: var(--white);
}
.info {
margin: 0;
@ -58,6 +63,7 @@ class AppInfo extends connect(store)(LitElement) {
display: inline-block;
width:100%;
padding-bottom:8px;
color: var(--black);
}
.blue {
color: #03a9f4;
@ -67,7 +73,7 @@ class AppInfo extends connect(store)(LitElement) {
display: inline;
}
.black {
color: black;
color: var(--black);
margin: 0;
font-size: 14px;
font-weight:200;

View File

@ -9,6 +9,7 @@ import './wallet-profile.js'
import './app-info.js'
import './sidenav-menu.js'
import './show-plugin.js'
import './qort-theme-toggle.js'
import '@material/mwc-drawer'
@ -30,29 +31,38 @@ class AppView extends connect(store)(LitElement) {
:host {
--app-drawer-width: 260px;
}
app-drawer-layout:not([narrow]) [drawer-toggle]:not(sidenav-menu) {
display: none;
}
app-drawer {
box-shadow: var(--shadow-2);
background: var(--mdc-theme-surface);
background: var(--white);
}
app-header {
box-shadow: var(--shadow-2);
}
app-toolbar {
background: var(--mdc-theme-surface);
color: var(--mdc-theme-on-surface);
background: var(--white);
color: var(--black);
border-top: var(--border);
}
#sideBar {
height: 100vh;
display: flex;
flex-direction: column;
background: var(--white);
}
.sideBarMenu{
overflow-y: auto;
flex: 1 1;
}
#sideBar::-webkit-scrollbar {
width: 7px;
background-color: transparent;
@ -94,6 +104,8 @@ class AppView extends connect(store)(LitElement) {
<img src="${this.config.coin.logo}" style="height:32px; padding-left:12px;">
</span>
</div>
<qort-theme-toggle></qort-theme-toggle>
<div>&nbsp;&nbsp;</div>
<div style="display:inline">
<paper-icon-button icon="icons:settings" @click=${ () => this.openSettings()} title="Settings" ></paper-icon-button>
</div>

View File

@ -0,0 +1,134 @@
import { LitElement, html, css } from 'lit'
import { svgSun, svgMoon } from '../../assets/js/svg.js'
class QortThemeToggle extends LitElement {
static get properties() {
return {
theme: {
type: String,
reflect: true
}
}
}
constructor() {
super();
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light';
}
static styles = [
css`
:host {
display: inline-block;
position: relative;
width: 54px;
height: 32px;
transform: translateY(-2px);
}
svg {
width: 32px;
height: 32px;
}
input {
cursor: pointer;
position: absolute;
z-index: 1;
opacity: 0;
width: 100%;
height: 100%;
}
.slider {
position: absolute;
cursor: pointer;
width: 100%;
height: 16px;
top: 50%;
transform: translateY(-50%);
border-radius: 1rem;
background-color: var(--graylight);
transition: all .4s ease;
}
.icon {
width: 32px;
height: 32px;
display: inline-block;
position: absolute;
top: 50%;
background: var(--graylight);
border: 2px solid var(--gray);
border-radius: 50%;
transition: transform 300ms ease;
}
:host([theme="light"]) .icon {
transform: translate(0, -50%);
}
input:checked ~ .icon,
:host([theme="dark"]) .icon {
transform: translate(calc(100% - 18px), -50%);
}
.moon {
display: none;
}
.moon svg {
transform: scale(0.6);
}
:host([theme="dark"]) .sun {
display: none;
}
:host([theme="dark"]) .moon {
display: inline-block;
}
`
];
render() {
return html`
<input type="checkbox" @change=${() => this.toggleTheme()}/>
<div class="slider"></div>
<div class="icon">
<span class="sun">${svgSun}</span>
<span class="moon">${svgMoon}</span>
</div>
`;
}
firstUpdated() {
this.initTheme();
}
toggleTheme() {
if (this.theme === 'light') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
this.dispatchEvent(
new CustomEvent('qort-theme-change', {
bubbles: true,
composed: true,
detail: this.theme,
}),
);
window.localStorage.setItem('qortalTheme', this.theme);
this.initTheme();
}
initTheme() {
document.querySelector('html').setAttribute('theme', this.theme);
}
}
window.customElements.define('qort-theme-toggle', QortThemeToggle);

View File

@ -20,7 +20,12 @@ class SecurityView extends connect(store)(LitElement) {
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--lumo-secondary-text-color: var(--sectxt);
--lumo-contrast-60pct: var(--vdicon);
}
.center-box {
position: relative;
top: 45%;
@ -28,6 +33,7 @@ class SecurityView extends connect(store)(LitElement) {
transform: translate(-50%, 0%);
text-align: center;
}
.q-button {
display: inline-flex;
flex-direction: column;
@ -61,7 +67,7 @@ class SecurityView extends connect(store)(LitElement) {
</p>
<div style="max-width: 500px; display: flex; justify-content: center; margin: auto;">
<mwc-icon style="padding: 10px; padding-left:0; padding-top: 42px;">password</mwc-icon>
<vaadin-password-field style="width:100%;" label="Password" id="downloadBackupPassword"></vaadin-password-field>
<vaadin-password-field style="width: 100%; color: var(--black);" label="Password" id="downloadBackupPassword"></vaadin-password-field>
</div>
<div style="max-width: 500px; display: flex; justify-content: center; margin: auto;">
<div @click=${() => this.downloadBackup()} class="q-button"> Download BackUp File </div>

View File

@ -28,39 +28,46 @@ class UserSettings extends connect(store)(LitElement) {
max-width: 100vw;
height: 100%;
max-height: 100vh;
background-color: #fff;
color: #333333;
background-color: var(--white);
color: var(--black);
line-height: 1.6;
}
.decline {
--mdc-theme-primary: var(--mdc-theme-error)
}
paper-dialog.userSettings {
width: 100%;
max-width: 100vw;
height: 100%;
max-height: 100vh;
background-color: #fff;
color: #333333;
background-color: var(--white);
color: var(--black);
line-height: 1.6;
overflow-y: auto;
}
.actions {
display:flex;
justify-content: space-between;
padding: 0 4em;
margin: 15px 0 -2px 0;
}
.close-icon {
font-size: 36px;
}
.close-icon:hover {
cursor: pointer;
opacity: .6;
}
.buttons {
text-align:right;
}
.container {
max-width: 90vw;
margin-left: auto;
@ -68,107 +75,127 @@ class UserSettings extends connect(store)(LitElement) {
margin-top: 20px;
padding: .6em;
}
ul {
list-style: none;
padding: 0;
margin-bottom: 0;
}
.leftBar {
background-color: #fff;
color: #333333;
border: 1px solid #a1a1a1;
background-color: var(--white);
color: var(--black);
border: 1px solid var(--border);
padding: 20px 0 0 0;
border-radius: 5px;
}
.leftBar img {
margin: 0 auto;
width: 75%;
height: 75%;
text-align: center;
}
.leftBar .slug {
text-align: center;
margin-top: 20px;
color: #333333;
color: var(--black);
font-size: 16px;
font-weight: 600;
margin-bottom: 7px;
}
.leftBar ul li {
border-bottom: 1px solid #DDD;
border-bottom: 1px solid var(--border);
}
.leftBar ul li:last-child {
border-bottom: none;
}
.leftBar ul li a {
color: #333333;
color: var(--black);
font-size: 16px;
font-weight: 400;
text-decoration: none;
padding: .9em;
display: block;
}
.leftBar ul li a i {
margin-right: 8px;
font-size: 16px;
}
.leftBar ul li a:hover {
background-color: #f6f6f6;
background-color: var(--menuhover);
color: #515151;
}
.leftBar ul li:active {
border-bottom: none;
}
.leftBar ul li a.active {
color: #515151;
background-color: #eee;
background-color: var(--menuactive);
border-left: 2px solid #515151;
margin-left: -2px;
}
.mainPage {
background-color: #fff;
color: #333333;
border: 1px solid #a1a1a1;
background-color: var(--white);
color: var(--black);
border: 1px solid var(--border);
padding: 20px 0 10px 0;
border-radius: 5px;
font-size: 16px;
text-align: center;
min-height: 460px;
}
@media(max-width:700px) {
.mainPage {
margin-top: 30px;
}
}
@media(min-width:765px) {
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.actions {
display:flex;
justify-content: space-between;
padding: 0 4em;
margin: 15px 0 -25px 0;
}
.container {
padding: 2em;
}
.wrapper {
display: grid;
grid-template-columns: 1fr 3fr;
grid-gap: 30px;
}
.wrapper > .mainPage {
padding: 2em;
}
.leftBar {
text-align: left;
max-height: 403px;
max-width: 400px;
font-size: 16px;
}
.mainPage {
font-size: 16px;
}

View File

@ -20,11 +20,12 @@ class SidenavMenu extends connect(store)(LitElement) {
.mcd-menu {
list-style: none;
padding: 0px 0px;
background: rgb(255, 255, 255);
background: var(--white);
border-radius: 2px;
width: 100%;
outline: none;
}
.mcd-menu li {
position: relative;
line-height: 48px;
@ -32,17 +33,19 @@ class SidenavMenu extends connect(store)(LitElement) {
padding: 2px;
list-style: none;
}
.mcd-menu li a {
display: block;
text-decoration: none;
padding-left: 20px;
color: var(--mdc-theme-on-surface);
color: var(--mainmenutext);
text-align: left;
height: 48px;
position: relative;
border-bottom: 1px solid #EEE;
border-bottom: 1px solid var(--border);
outline: none;
}
.mcd-menu li a mwc-icon {
float: left;
margin: 0 10px 0 0;
@ -65,21 +68,24 @@ class SidenavMenu extends connect(store)(LitElement) {
.mcd-menu li:hover > a mwc-icon {
opacity: 1;
}
.mcd-menu li:hover a span {
opacity: 1;
outline: none;
}
.mcd-menu li:hover > a {
background: #f8f8f8;
color: #515151;
background: var(--menuhover);
color: var(--mainmenutexthover);
}
.mcd-menu li a.active {
position: relative;
color: #515151;
background-color: #eee;
background-color: var(--menuactive);
outline: none;
}
.mcd-menu li a.active:before {
content: "";
position: absolute;
@ -123,6 +129,7 @@ class SidenavMenu extends connect(store)(LitElement) {
border-left: 4px solid #515151;
outline: none;
}
.mcd-menu li ul:before {
content: "";
position: absolute;
@ -133,6 +140,7 @@ class SidenavMenu extends connect(store)(LitElement) {
border-top: 5px solid transparent;
outline: none;
}
.mcd-menu li:hover > ul,
.mcd-menu li ul li:hover > ul {
display: block;
@ -145,14 +153,16 @@ class SidenavMenu extends connect(store)(LitElement) {
.mcd-menu li ul li a {
text-align: left;
border: 0;
border-bottom: 1px solid #EEE;
border-bottom: 1px solid var(--border);
height: auto;
outline: none;
}
.mcd-menu li ul li a mwc-icon {
display: inline-block;
margin: 0 10px 0 0;
}
.mcd-menu li ul li ul {
left: 230px;
top: 0;
@ -160,6 +170,7 @@ class SidenavMenu extends connect(store)(LitElement) {
border-left: 4px solid #515151;
outline: none;
}
.mcd-menu li ul li ul:before {
content: "";
position: absolute;
@ -170,6 +181,7 @@ class SidenavMenu extends connect(store)(LitElement) {
border-top: 5px solid transparent;
outline: none;
}
.mcd-menu li ul li:hover > ul {
top: 0px;
left: 200px;
@ -186,10 +198,6 @@ class SidenavMenu extends connect(store)(LitElement) {
render() {
return html`
<style>
</style>
<div>
<ul class="mcd-menu">
${this.urls.map(myPlugin => myPlugin.menus.length === 0 ? html`

View File

@ -35,10 +35,12 @@ class WalletProfile extends connect(store)(LitElement) {
<style>
#profileInMenu {
padding: 12px;
border-top: 1px solid rgb(238, 238, 238);
background: rgb(255, 255, 255);
border-top: var(--border);
background: var(--white);
color: var(--black);
}
#profileInMenu:hover {
/* cursor:pointer; */
}
#accountIcon {
font-size:48px;
@ -63,7 +65,6 @@ class WalletProfile extends connect(store)(LitElement) {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin:0;
margin-top:8px;
font-size:11px;

View File

@ -41,7 +41,7 @@ class CopyTextMenu extends connect(store)(LitElement) {
position: absolute;
pointer-events: none;
padding: 5px, 0;
border: 1px solid #B2B2B2;
border: 1px solid var(--border);
min-width: 150px;
max-width: 300px;
background: #F9F9F9;

View File

@ -0,0 +1 @@
export const UI_VERSION = "1.7.4";

View File

@ -1,19 +1,9 @@
import { LitElement, html } from 'lit-element'
import { LitElement, html } from 'lit'
// import '../styles/styles.scss'
import './styles.scss'
import './app-theme.js'
class AppStyles extends LitElement {
// static get styles () {
// return [
// css`
// html, * {
// color: var(--color, green);
// }
// `
// ]
// }
/* Disable shadow DOM, so that the styles DO bleed */
createRenderRoot () {
@ -23,12 +13,6 @@ class AppStyles extends LitElement {
render () {
return html`
<style>
/* NOT THE IDEAL SOLUTION. Would be better to compile sass and inline it here...
someone can do this for me at some point...or I could */
/* https://material.io/develop/web/components/layout-grid/ */
/* @import url('/'); */
* {
/* from https://codepen.io/sdthornton/pen/wBZdXq/ */
--shadow-1: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
@ -36,7 +20,6 @@ class AppStyles extends LitElement {
--shadow-3: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
--shadow-4: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
--shadow-5: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22);
--paper-input-container-focus-color: var(--mdc-theme-secondary);
font-family: "Roboto", sans-serif;
@ -65,20 +48,15 @@ class AppStyles extends LitElement {
_windowResized () {
const ua = navigator.userAgent
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i.test(ua)
// console.log(isMobile, 'MOBILE')
const isChrome = /Chrome/i.test(ua)
const isSafari = /Version\/[\d\.]+.*Safari/.test(ua)
if (isMobile && isChrome) {
this.windowHeight = html`calc(100vh - 56px)`
// document.body.style.setProperty('--window-height', 'calc(100vh - 56px)')
// console.log('not same')
} else if (isMobile && isSafari) {
this.windowHeight = html`calc(100vh - 72px)`
} else {
this.windowHeight = html`100vh`
// document.body.style.setProperty('--window-height', '100vh')
// console.log('same')
}
}
}

View File

@ -1,17 +1,8 @@
import { LitElement, html } from 'lit-element'
import { LitElement, html } from 'lit'
import { connect } from 'pwa-helpers'
import { store } from '../store.js'
class AppTheme extends connect(store)(LitElement) {
// static get styles () {
// return [
// css`
// html, * {
// color: var(--color, green);
// }
// `
// ]
// }
static get properties () {
return {

View File

@ -0,0 +1,16 @@
html {
/* color pallet */
--white: #ffffff;
--black: #080808;
--gray: #c8c8c8;
--graylight: #bbbbbb;
--plugback: #ffffff;
}
html[theme="dark"] {
--white: #36393f;
--black: #f8f8f8;
--gray: #d8d8d8;
--graylight: #dddddd;
--plugback: #36393f;
}

View File

@ -36,12 +36,12 @@
"@polymer/paper-spinner": "^3.0.2",
"@rollup/plugin-alias": "^3.1.9",
"@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-commonjs": "^21.0.2",
"@rollup/plugin-node-resolve": "^13.1.3",
"@rollup/plugin-replace": "^4.0.0",
"@vaadin/button": "^22.0.5",
"@vaadin/grid": "^22.0.5",
"@vaadin/icons": "^22.0.5",
"@vaadin/button": "^23.0.1",
"@vaadin/grid": "^23.0.1",
"@vaadin/icons": "^23.0.1",
"epml": "^0.3.3",
"html-escaper": "^3.0.3",
"lit": "^2.2.0",

View File

@ -23,26 +23,34 @@ class ChatHead extends LitElement {
cursor: pointer;
width: 100%;
}
li:hover {
background-color: #eee;
background-color: var(--menuhover);
}
.active {
background: #ebebeb;
background: var(--menuactive);
border-left: 4px solid #3498db;
}
.img-icon {
float: left;
font-size:40px;
color: var(--black);
}
.about {
margin-top: 8px;
}
.about {
padding-left: 8px;
}
.status {
color: #92959e;
}
.clearfix:after {
visibility: hidden;
display: block;
@ -74,7 +82,7 @@ class ChatHead extends LitElement {
<li @click=${() => this.getUrl(this.chatInfo.url)} class="clearfix ${this.activeChatHeadUrl === this.chatInfo.url ? 'active' : ''}">
<mwc-icon class="img-icon">account_circle</mwc-icon>
<div class="about">
<div class="name"><span style="float:left; padding-left: 8px;">${this.chatInfo.groupName ? this.chatInfo.groupName : this.chatInfo.name !== undefined ? this.chatInfo.name : this.chatInfo.address.substr(0, 15)} </span> <mwc-icon style="float:right; padding: 0 1rem;">${this.chatInfo.groupId !== undefined ? 'lock_open' : 'lock'}</mwc-icon> </div>
<div class="name"><span style="float:left; padding-left: 8px; color: var(--black);">${this.chatInfo.groupName ? this.chatInfo.groupName : this.chatInfo.name !== undefined ? this.chatInfo.name : this.chatInfo.address.substr(0, 15)} </span> <mwc-icon style="float:right; padding: 0 1rem; color: var(--black);">${this.chatInfo.groupId !== undefined ? 'lock_open' : 'lock'}</mwc-icon> </div>
</div>
</li>
`

View File

@ -39,11 +39,13 @@ class ChatPage extends LitElement {
html {
scroll-behavior: smooth;
}
.chat-text-area {
display: flex;
justify-content: center;
overflow: hidden;
}
.chat-text-area .typing-area {
display: flex;
flex-direction: row;
@ -53,12 +55,16 @@ class ChatPage extends LitElement {
box-sizing: border-box;
padding: 5px;
margin-bottom: 8px;
border: 1px solid rgba(0, 0, 0, 0.3);
border: 1px solid var(--black);
border-radius: 10px;
background: #f1f1f1;
color: var(--black);
}
.chat-text-area .typing-area textarea {
display: none;
}
.chat-text-area .typing-area .chat-editor {
border-color: transparent;
flex: 1;
@ -68,6 +74,7 @@ class ChatPage extends LitElement {
padding: 0;
border: none;
}
.chat-text-area .typing-area .emoji-button {
width: 45px;
height: 40px;
@ -77,7 +84,9 @@ class ChatPage extends LitElement {
background: transparent;
cursor: pointer;
max-height: 40px;
color: var(--black);
}
.float-left {
float: left;
}
@ -88,15 +97,11 @@ class ChatPage extends LitElement {
`
}
updated(changedProps) {
}
constructor() {
super()
this.getOldMessage = this.getOldMessage.bind(this)
this._sendMessage = this._sendMessage.bind(this)
this._downObserverhandler = this._downObserverhandler.bind(this)
this.selectedAddress = {}
this.chatId = ''
this.myAddress = ''
@ -122,7 +127,7 @@ class ChatPage extends LitElement {
<div class="chat-text-area">
<div class="typing-area">
<textarea tabindex='1' ?autofocus=${true} ?disabled=${this.isLoading || this.isLoadingMessages} id="messageBox" rows="1"></textarea>
<textarea style="color: var(--black);" tabindex='1' ?autofocus=${true} ?disabled=${this.isLoading || this.isLoadingMessages} id="messageBox" rows="1"></textarea>
<iframe class="chat-editor" id="_chatEditorDOM" tabindex="-1"></iframe>
<button class="emoji-button" ?disabled=${this.isLoading || this.isLoadingMessages}>
@ -133,6 +138,113 @@ class ChatPage extends LitElement {
`
}
firstUpdated() {
// TODO: Load and fetch messages from localstorage (maybe save messages to localstorage...)
this.emojiPickerHandler = this.shadowRoot.querySelector('.emoji-button');
this.mirrorChatInput = this.shadowRoot.getElementById('messageBox');
this.chatMessageInput = this.shadowRoot.getElementById('_chatEditorDOM');
document.addEventListener('keydown', (e) => {
if (!this.chatEditor.content.body.matches(':focus')) {
// WARNING: Deprecated methods from KeyBoard Event
if (e.code === "Space" || e.keyCode === 32 || e.which === 32) {
this.chatEditor.insertText('&nbsp;');
} else if (inputKeyCodes.includes(e.keyCode)) {
this.chatEditor.insertText(e.key);
return this.chatEditor.focus();
} else {
return this.chatEditor.focus();
}
};
});
// Init EmojiPicker
this.emojiPicker = new EmojiPicker({
style: "twemoji",
twemojiBaseUrl: '/emoji/',
showPreview: false,
showVariants: false,
showAnimation: false,
position: 'top-start',
boxShadow: 'rgba(4, 4, 5, 0.15) 0px 0px 0px 1px, rgba(0, 0, 0, 0.24) 0px 8px 16px 0px'
});
this.emojiPicker.on('emoji', selection => {
const emojiHtmlString = `<img class="emoji" draggable="false" alt="${selection.emoji}" src="${selection.url}">`;
this.chatEditor.insertEmoji(emojiHtmlString);
});
// Attach Event Handler
this.emojiPickerHandler.addEventListener('click', () => this.emojiPicker.togglePicker(this.emojiPickerHandler));
const getAddressPublicKey = () => {
parentEpml.request('apiCall', {
type: 'api',
url: `/addresses/publickey/${this._chatId}`
}).then(res => {
if (res.error === 102) {
this._publicKey.key = ''
this._publicKey.hasPubKey = false
this.fetchChatMessages(this._chatId)
} else if (res !== false) {
this._publicKey.key = res
this._publicKey.hasPubKey = true
this.fetchChatMessages(this._chatId)
} else {
this._publicKey.key = ''
this._publicKey.hasPubKey = false
this.fetchChatMessages(this._chatId)
}
})
};
setTimeout(() => {
this.chatId.includes('direct') === true ? this.isReceipient = true : this.isReceipient = false;
this._chatId = this.chatId.split('/')[1];
const placeholder = this.isReceipient === true ? `Message ${this._chatId}` : 'Message...';
this.chatEditorPlaceholder = placeholder;
this.isReceipient ? getAddressPublicKey() : this.fetchChatMessages(this._chatId);
// Init ChatEditor
this.initChatEditor();
}, 100)
parentEpml.ready().then(() => {
parentEpml.subscribe('selected_address', async selectedAddress => {
this.selectedAddress = {}
selectedAddress = JSON.parse(selectedAddress)
if (!selectedAddress || Object.entries(selectedAddress).length === 0) return
this.selectedAddress = selectedAddress
})
parentEpml.request('apiCall', {
url: `/addresses/balance/${window.parent.reduxStore.getState().app.selectedAddress.address}`
}).then(res => {
this.balance = res
})
parentEpml.subscribe('frame_paste_menu_switch', async res => {
res = JSON.parse(res)
if (res.isOpen === false && this.isPasteMenuOpen === true) {
this.pasteToTextBox(textarea)
this.isPasteMenuOpen = false
}
})
})
parentEpml.imReady();
}
updated(changedProps) {
}
renderChatScroller(initialMessages) {
return html`<chat-scroller .initialMessages=${initialMessages} .emojiPicker=${this.emojiPicker} .escapeHTML=${escape} .getOldMessage=${this.getOldMessage} > </chat-scroller>`
@ -204,8 +316,6 @@ class ChatPage extends LitElement {
this.newMessages = this.newMessages.concat(_newMessages)
}
}
/**
@ -574,112 +684,6 @@ class ChatPage extends LitElement {
observer.observe(downObserver)
}
firstUpdated() {
// TODO: Load and fetch messages from localstorage (maybe save messages to localstorage...)
this.emojiPickerHandler = this.shadowRoot.querySelector('.emoji-button');
this.mirrorChatInput = this.shadowRoot.getElementById('messageBox');
this.chatMessageInput = this.shadowRoot.getElementById('_chatEditorDOM');
document.addEventListener('keydown', (e) => {
if (!this.chatEditor.content.body.matches(':focus')) {
// WARNING: Deprecated methods from KeyBoard Event
if (e.code === "Space" || e.keyCode === 32 || e.which === 32) {
this.chatEditor.insertText('&nbsp;');
} else if (inputKeyCodes.includes(e.keyCode)) {
this.chatEditor.insertText(e.key);
return this.chatEditor.focus();
} else {
return this.chatEditor.focus();
}
};
});
// Init EmojiPicker
this.emojiPicker = new EmojiPicker({
style: "twemoji",
twemojiBaseUrl: '/emoji/',
showPreview: false,
showVariants: false,
showAnimation: false,
position: 'top-start',
boxShadow: 'rgba(4, 4, 5, 0.15) 0px 0px 0px 1px, rgba(0, 0, 0, 0.24) 0px 8px 16px 0px'
});
this.emojiPicker.on('emoji', selection => {
const emojiHtmlString = `<img class="emoji" draggable="false" alt="${selection.emoji}" src="${selection.url}">`;
this.chatEditor.insertEmoji(emojiHtmlString);
});
// Attach Event Handler
this.emojiPickerHandler.addEventListener('click', () => this.emojiPicker.togglePicker(this.emojiPickerHandler));
const getAddressPublicKey = () => {
parentEpml.request('apiCall', {
type: 'api',
url: `/addresses/publickey/${this._chatId}`
}).then(res => {
if (res.error === 102) {
this._publicKey.key = ''
this._publicKey.hasPubKey = false
this.fetchChatMessages(this._chatId)
} else if (res !== false) {
this._publicKey.key = res
this._publicKey.hasPubKey = true
this.fetchChatMessages(this._chatId)
} else {
this._publicKey.key = ''
this._publicKey.hasPubKey = false
this.fetchChatMessages(this._chatId)
}
})
};
setTimeout(() => {
this.chatId.includes('direct') === true ? this.isReceipient = true : this.isReceipient = false;
this._chatId = this.chatId.split('/')[1];
const placeholder = this.isReceipient === true ? `Message ${this._chatId}` : 'Message...';
this.chatEditorPlaceholder = placeholder;
this.isReceipient ? getAddressPublicKey() : this.fetchChatMessages(this._chatId);
// Init ChatEditor
this.initChatEditor();
}, 100)
parentEpml.ready().then(() => {
parentEpml.subscribe('selected_address', async selectedAddress => {
this.selectedAddress = {}
selectedAddress = JSON.parse(selectedAddress)
if (!selectedAddress || Object.entries(selectedAddress).length === 0) return
this.selectedAddress = selectedAddress
})
parentEpml.request('apiCall', {
url: `/addresses/balance/${window.parent.reduxStore.getState().app.selectedAddress.address}`
}).then(res => {
this.balance = res
})
parentEpml.subscribe('frame_paste_menu_switch', async res => {
res = JSON.parse(res)
if (res.isOpen === false && this.isPasteMenuOpen === true) {
this.pasteToTextBox(textarea)
this.isPasteMenuOpen = false
}
})
})
parentEpml.imReady();
}
pasteToTextBox(textarea) {
// Return focus to the window

View File

@ -43,6 +43,7 @@ class ChatScroller extends LitElement {
margin: 0;
padding: 20px;
}
.chat-list {
overflow-y: auto;
height: 91vh;
@ -53,6 +54,10 @@ class ChatScroller extends LitElement {
margin-bottom: 15px;
}
.message-data-name {
color: var(--black);
}
.message-data-time {
color: #a8aab1;
font-size: 13px;

View File

@ -18,12 +18,24 @@ class ChatWelcomePage extends LitElement {
messages: { type: Array },
btnDisable: { type: Boolean },
isLoading: { type: Boolean },
balance: { type: Number }
balance: { type: Number },
theme: { type: String, reflect: true }
}
}
static get styles() {
return css`
* {
--mdc-theme-primary: rgb(3, 169, 244);
--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);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
}
@keyframes moveInBottom {
0% {
opacity: 0;
@ -47,7 +59,7 @@ class ChatWelcomePage extends LitElement {
display: block;
overflow: hidden;
font-size: 40px;
color: black;
color: var(--black);
font-weight: 400;
text-align: center;
white-space: pre-wrap;
@ -72,6 +84,7 @@ class ChatWelcomePage extends LitElement {
.img-icon {
font-size: 150px;
color: var(--black);
}
.start-chat {
@ -83,8 +96,8 @@ class ChatWelcomePage extends LitElement {
border-radius: 20px;
padding-left: 25px;
padding-right: 25px;
color: white;
background: #6a6c75;
color: var(--white);
background: var(--tradehead);
width: 50%;
font-size: 17px;
cursor: pointer;
@ -125,7 +138,7 @@ class ChatWelcomePage extends LitElement {
}
h2, h3, h4, h5 {
color:#333;
color:# var(--black);
font-weight: 400;
}
@ -179,6 +192,7 @@ class ChatWelcomePage extends LitElement {
this.messages = []
this.btnDisable = false
this.isLoading = false
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
@ -191,7 +205,7 @@ class ChatWelcomePage extends LitElement {
<div class="sub-main">
<div class="center-box">
<mwc-icon class="img-icon">chat</mwc-icon><br>
<span style="font-size: 20px;">${this.myAddress.address}</span>
<span style="font-size: 20px; color: var(--black);">${this.myAddress.address}</span>
<div class="start-chat" @click=${() => this.shadowRoot.querySelector('#startSecondChatDialog').show()}>New Private Message</div>
</div>
</div>
@ -224,6 +238,11 @@ class ChatWelcomePage extends LitElement {
}
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 250)
const stopKeyEventPropagation = (e) => {
e.stopPropagation();
return false;
@ -260,6 +279,16 @@ class ChatWelcomePage extends LitElement {
parentEpml.imReady()
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
_sendMessage() {
this.isLoading = true

View File

@ -29,7 +29,8 @@ class GroupManagement extends LitElement {
error: { type: Boolean },
message: { type: String },
removeError: { type: Boolean },
removeMessage: { type: String }
removeMessage: { type: String },
theme: { type: String, reflect: true }
}
}
@ -42,10 +43,16 @@ class GroupManagement extends LitElement {
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--lumo-secondary-text-color: var(--sectxt);
--lumo-contrast-60pct: var(--vdicon);
--_lumo-grid-border-color: var(--border);
--_lumo-grid-secondary-border-color: var(--border2);
}
#group-management-page {
background: #fff;
background: var(--white);
padding: 12px 24px;
}
@ -68,7 +75,7 @@ class GroupManagement extends LitElement {
}
.divCard {
border: 1px solid #eee;
border: 1px solid var(--border);
padding: 1em;
box-shadow: 0 .3px 1px 0 rgba(0,0,0,0.14), 0 1px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20);
margin-bottom: 2em;
@ -79,7 +86,7 @@ class GroupManagement extends LitElement {
}
h2, h3, h4, h5 {
color:#333;
color: var(--black);
font-weight: 400;
}
@ -133,6 +140,7 @@ class GroupManagement extends LitElement {
this.createFee = 0.001
this.joinFee = 0.001
this.leaveFee = 0.001
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
@ -156,7 +164,7 @@ class GroupManagement extends LitElement {
}}></vaadin-grid-column>
</vaadin-grid>
${this.isEmptyArray(this.joinedGroups) ? html`
Not a member of any groups!
<span style="color: var(--black);">Not a member of any groups!</span>
`: ''}
</div>
@ -171,7 +179,7 @@ class GroupManagement extends LitElement {
}}></vaadin-grid-column>
</vaadin-grid>
${this.isEmptyArray(this.publicGroups) ? html`
No Open Public Groups available!
<span style="color: var(--black);">No Open Public Groups available!</span>
`: ''}
</div>
@ -420,6 +428,11 @@ class GroupManagement extends LitElement {
}
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
this.unitCreateFee()
this.unitJoinFee()
this.unitLeaveFee()
@ -491,6 +504,16 @@ class GroupManagement extends LitElement {
parentEpml.imReady()
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
async unitCreateFee() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -5,16 +5,26 @@ const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
class Messaging extends LitElement {
static get properties() {
return {}
return {
theme: { type: String, reflect: true }
}
}
static get styles() {
return css`
* {
--mdc-theme-primary: rgb(3, 169, 244);
--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);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
}
#page {
background: #fff;
background: var(--white);
padding: 12px 24px;
}
@ -24,7 +34,7 @@ class Messaging extends LitElement {
}
h3, h4, h5 {
color:#333;
color: var(--black);
font-weight: 400;
}
@ -57,24 +67,25 @@ class Messaging extends LitElement {
}
.divCard {
border: 1px solid #eee;
border: 1px solid var(--border);
padding: 1em;
box-shadow: 0 .3px 1px 0 rgba(0,0,0,0.14), 0 1px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20);
margin-bottom: 1.5rem;
}
p {
color:#333;
color: var(--black);
}
ul, ul li {
color:#333;
color: var(--black);
}
`
}
constructor() {
super()
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
@ -95,8 +106,6 @@ class Messaging extends LitElement {
These messages <strong>are able</strong> to be <strong>sent to groups or individual accounts</strong>, and are essentially <strong>the 'e-mail' of Qortal</strong>.
Use these messages if you intend on the message being a <strong>PERMANENT message</strong> that stays when and where you send it.</p>
<!-- <span style="display: block; text-align: center"><strong>- more info -</strong></span> -->
<ul>
<li style="font-size: 17px; padding: 10px;">There are no @ in Qortal Chain Messaging, only 'registered names'. As the registered names on the chain can only be registered ONCE. Therefore, there are NO DUPLICATES.</li>
<li style="font-size: 17px; padding: 10px;">Chain Messages LAST FOREVER</li>
@ -125,18 +134,12 @@ class Messaging extends LitElement {
`
}
getUrl(pageId) {
this.onPageNavigation(`/app/${pageId}`)
}
onPageNavigation(pageUrl) {
parentEpml.request('setPageUrl', pageUrl)
}
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
window.addEventListener("contextmenu", (event) => {
event.preventDefault();
@ -178,11 +181,27 @@ class Messaging extends LitElement {
}
})
})
parentEpml.imReady()
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
getUrl(pageId) {
this.onPageNavigation(`/app/${pageId}`)
}
onPageNavigation(pageUrl) {
parentEpml.request('setPageUrl', pageUrl)
}
_textMenu(event) {
const getSelectedText = () => {

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
overflow: hidden;
}
</style>

View File

@ -23,16 +23,22 @@ class Chat extends LitElement {
messages: { type: Array },
btnDisable: { type: Boolean },
isLoading: { type: Boolean },
balance: { type: Number }
balance: { type: Number },
theme: { type: String, reflect: true }
}
}
static get styles() {
return css`
* {
--mdc-theme-primary: rgb(3, 169, 244);
--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);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
}
paper-spinner-lite{
@ -56,7 +62,7 @@ class Chat extends LitElement {
.container {
margin: 0 auto;
width: 100%;
background: #fff;
background: var(--white);
}
.people-list {
@ -76,8 +82,8 @@ class Chat extends LitElement {
border: none;
display: inline-block;
padding: 14px;
color: white;
background: #6a6c75;
color: var(--white);
background: var(--tradehead);
width: 90%;
font-size: 15px;
text-align: center;
@ -100,7 +106,7 @@ class Chat extends LitElement {
width: 80vw;
height: 100vh;
float: left;
background: #fff;
background: var(--white);
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
color: #434651;
@ -120,8 +126,8 @@ class Chat extends LitElement {
left: 20vw;
right: 0;
z-index: 5;
background: #6a6c75;
color: white;
background: var(--tradehead);
color: var(--white);
border-radius: 0 0 8px 8px;
min-height: 25px;
transition: opacity .15s;
@ -146,7 +152,7 @@ class Chat extends LitElement {
right: 0;
bottom: 100%;
left: 20vw;
border-bottom: 2px solid white;
border-bottom: 2px solid var(--white);
overflow-y: hidden;
height: 100vh;
box-sizing: border-box;
@ -202,6 +208,7 @@ class Chat extends LitElement {
clear: both;
height: 0;
}
.red {
--mdc-theme-primary: red;
}
@ -211,7 +218,7 @@ class Chat extends LitElement {
}
h2, h3, h4, h5 {
color:#333;
color: var(--black);
font-weight: 400;
}
@ -219,16 +226,19 @@ class Chat extends LitElement {
display: hidden !important;
visibility: none !important;
}
.details {
display: flex;
font-size: 18px;
}
.title {
font-weight:600;
font-size:12px;
line-height: 32px;
opacity: 0.66;
}
.input {
width: 100%;
border: none;
@ -239,6 +249,7 @@ class Chat extends LitElement {
resize: none;
background: #eee;
}
.textarea {
width: 100%;
border: none;
@ -271,17 +282,13 @@ class Chat extends LitElement {
this.messages = []
this.btnDisable = false
this.isLoading = false
this.showNewMesssageBar = this.showNewMesssageBar.bind(this)
this.hideNewMesssageBar = this.hideNewMesssageBar.bind(this)
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
return html`
<style>
</style>
<div class="container clearfix">
<div class="people-list" id="people-list">
<div class="search">
@ -336,63 +343,12 @@ class Chat extends LitElement {
`
}
renderChatWelcomePage() {
return html`<chat-welcome-page myAddress=${JSON.stringify(this.selectedAddress)}></chat-welcome-page>`
}
renderChatHead(chatHeadArr) {
let tempUrl = document.location.href
let splitedUrl = decodeURI(tempUrl).split('?')
let activeChatHeadUrl = splitedUrl[1] === undefined ? '' : splitedUrl[1]
return chatHeadArr.map(eachChatHead => {
return html`<chat-head activeChatHeadUrl=${activeChatHeadUrl} chatInfo=${JSON.stringify(eachChatHead)}></chat-head>`
})
}
renderChatPage(chatId) {
// Check for the chat ID from and render chat messages
// Else render Welcome to Q-CHat
// TODO: DONE: Do the above in the ChatPage
return html`<chat-page .hideNewMesssageBar=${this.hideNewMesssageBar} .showNewMesssageBar=${this.showNewMesssageBar} myAddress=${window.parent.reduxStore.getState().app.selectedAddress.address} chatId=${chatId}></chat-page>`
}
setChatHeads(chatObj) {
let groupList = chatObj.groups.map(group => group.groupId === 0 ? { groupId: group.groupId, url: `group/${group.groupId}`, groupName: "Qortal General Chat", timestamp: group.timestamp === undefined ? 2 : group.timestamp } : { ...group, timestamp: group.timestamp === undefined ? 1 : group.timestamp, url: `group/${group.groupId}` })
let directList = chatObj.direct.map(dc => {
return { ...dc, url: `direct/${dc.address}` }
})
const compareNames = (a, b) => {
return a.groupName.localeCompare(b.groupName)
}
groupList.sort(compareNames)
let chatHeadMasterList = [...groupList, ...directList]
const compareArgs = (a, b) => {
return b.timestamp - a.timestamp
}
this.chatHeads = chatHeadMasterList.sort(compareArgs)
}
getChatHeadFromState(chatObj) {
if (chatObj === undefined) {
return
} else {
this.chatHeadsObj = chatObj
this.setChatHeads(chatObj)
}
}
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 250)
const stopKeyEventPropagation = (e) => {
e.stopPropagation();
return false;
@ -455,6 +411,7 @@ class Chat extends LitElement {
}
let configLoaded = false
parentEpml.ready().then(() => {
parentEpml.subscribe('selected_address', async selectedAddress => {
this.selectedAddress = {}
@ -485,10 +442,73 @@ class Chat extends LitElement {
}
})
})
parentEpml.imReady()
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
renderChatWelcomePage() {
return html`<chat-welcome-page myAddress=${JSON.stringify(this.selectedAddress)}></chat-welcome-page>`
}
renderChatHead(chatHeadArr) {
let tempUrl = document.location.href
let splitedUrl = decodeURI(tempUrl).split('?')
let activeChatHeadUrl = splitedUrl[1] === undefined ? '' : splitedUrl[1]
return chatHeadArr.map(eachChatHead => {
return html`<chat-head activeChatHeadUrl=${activeChatHeadUrl} chatInfo=${JSON.stringify(eachChatHead)}></chat-head>`
})
}
renderChatPage(chatId) {
// Check for the chat ID from and render chat messages
// Else render Welcome to Q-CHat
// TODO: DONE: Do the above in the ChatPage
return html`<chat-page .hideNewMesssageBar=${this.hideNewMesssageBar} .showNewMesssageBar=${this.showNewMesssageBar} myAddress=${window.parent.reduxStore.getState().app.selectedAddress.address} chatId=${chatId}></chat-page>`
}
setChatHeads(chatObj) {
let groupList = chatObj.groups.map(group => group.groupId === 0 ? { groupId: group.groupId, url: `group/${group.groupId}`, groupName: "Qortal General Chat", timestamp: group.timestamp === undefined ? 2 : group.timestamp } : { ...group, timestamp: group.timestamp === undefined ? 1 : group.timestamp, url: `group/${group.groupId}` })
let directList = chatObj.direct.map(dc => {
return { ...dc, url: `direct/${dc.address}` }
})
const compareNames = (a, b) => {
return a.groupName.localeCompare(b.groupName)
}
groupList.sort(compareNames)
let chatHeadMasterList = [...groupList, ...directList]
const compareArgs = (a, b) => {
return b.timestamp - a.timestamp
}
this.chatHeads = chatHeadMasterList.sort(compareArgs)
}
getChatHeadFromState(chatObj) {
if (chatObj === undefined) {
return
} else {
this.chatHeadsObj = chatObj
this.setChatHeads(chatObj)
}
}
_sendMessage() {
this.isLoading = true

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -18,7 +18,8 @@ class MintingInfo extends LitElement {
nodeInfo: { type: Array },
sampleBlock: { type: Array },
addressInfo: { type: Array },
addressLevel: { type: Array }
addressLevel: { type: Array },
theme: { type: String, reflect: true }
}
}
@ -45,14 +46,14 @@ class MintingInfo extends LitElement {
font-weight:600;
font-size:20px;
line-height: 28px;
color:#000000;
color: var(--black);
}
.header-title {
display: block;
overflow: hidden;
font-size: 40px;
color: black;
color: var(--black);
font-weight: 400;
text-align: center;
white-space: pre-wrap;
@ -64,7 +65,7 @@ class MintingInfo extends LitElement {
.level-black {
font-size: 32px;
color: black;
color: var(--black);
font-weight: 400;
text-align: center;
margin-top: 2rem;
@ -95,7 +96,7 @@ class MintingInfo extends LitElement {
}
.content-box {
border: 1px solid #a1a1a1;
border: 1px solid var(--border);
border-radius: 10px;
padding: 10px 25px;
text-align: center;
@ -165,7 +166,7 @@ class MintingInfo extends LitElement {
}
.black {
color: #000000;
color: var(--black);
}
.red {
@ -192,6 +193,7 @@ class MintingInfo extends LitElement {
this.sampleBlock = [];
this.addressInfo = [];
this.addressLevel = [];
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light';
}
render() {
@ -355,6 +357,11 @@ class MintingInfo extends LitElement {
}
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
const getAdminInfo = () => {
parentEpml.request("apiCall", { url: `/admin/info` }).then((res) => {
setTimeout(() => { this.adminInfo = res; }, 1);
@ -422,6 +429,16 @@ class MintingInfo extends LitElement {
parentEpml.imReady();
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
renderMintingPage() {
if (this.addressInfo.error === 124) {
return "false"

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -23,7 +23,8 @@ class NameRegistration extends LitElement {
error: { type: Boolean },
message: { type: String },
removeError: { type: Boolean },
removeMessage: { type: String }
removeMessage: { type: String },
theme: { type: String, reflect: true }
}
}
@ -37,14 +38,19 @@ class NameRegistration extends LitElement {
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--_lumo-grid-border-color: var(--border);
--_lumo-grid-secondary-border-color: var(--border2);
}
#name-registration-page {
background: #fff;
background: var(--white);
padding: 12px 24px;
}
.divCard {
border: 1px solid #eee;
border: 1px solid var(--border);
padding: 1em;
box-shadow: 0 .3px 1px 0 rgba(0,0,0,0.14), 0 1px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20);
}
@ -54,7 +60,7 @@ class NameRegistration extends LitElement {
}
h2, h3, h4, h5 {
color:#333;
color: var(--black);
font-weight: 400;
}
@ -79,6 +85,7 @@ class NameRegistration extends LitElement {
this.btnDisable = false
this.registerNameLoading = false
this.fee = 0.001
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
@ -102,7 +109,7 @@ class NameRegistration extends LitElement {
}}></vaadin-grid-column>
</vaadin-grid>
${this.isEmptyArray(this.names) ? html`
No names registered by this account!
<span style="color: var(--black);">No names registered by this account!</span>
`: ''}
</div>
@ -123,7 +130,7 @@ class NameRegistration extends LitElement {
?active="${this.registerNameLoading}"
alt="Registering Name"></paper-spinner-lite>
</span>
<span ?hidden=${this.message === ''} style="${this.error ? 'color:red;' : ''}">
<span ?hidden=${this.message === ''} style="${this.error ? 'color:red;' : 'color:green;'}">
${this.message}
</span><br>
<span>
@ -151,6 +158,11 @@ class NameRegistration extends LitElement {
}
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
this.unitFee();
window.addEventListener("contextmenu", (event) => {
@ -202,6 +214,16 @@ class NameRegistration extends LitElement {
parentEpml.imReady()
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
renderAvatar(nameObj) {
let name = nameObj.name
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -7,8 +7,7 @@ import '@material/mwc-icon'
import '@material/mwc-textfield'
import '@material/mwc-button'
import '@material/mwc-dialog'
import '@vaadin/grid/vaadin-grid.js'
import '@vaadin/grid/theme/material/all-imports.js'
import '@vaadin/grid'
const parentEpml = new Epml({ type: "WINDOW", source: window.parent })
@ -31,7 +30,8 @@ class NodeManagement extends LitElement {
removeMintingAccountMessage: { type: String },
tempMintingAccount: { type: Object },
nodeConfig: { type: Object },
nodeDomain: { type: String }
nodeDomain: { type: String },
theme: { type: String, reflect: true }
};
}
@ -44,6 +44,12 @@ class NodeManagement extends LitElement {
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--lumo-secondary-text-color: var(--sectxt);
--lumo-contrast-60pct: var(--vdicon);
--_lumo-grid-border-color: var(--border);
--_lumo-grid-secondary-border-color: var(--border2);
}
paper-spinner-lite {
@ -54,7 +60,7 @@ class NodeManagement extends LitElement {
}
#node-management-page {
background: #fff;
background: var(--white);
}
mwc-textfield {
@ -77,7 +83,7 @@ class NodeManagement extends LitElement {
.node-card {
padding: 12px 24px;
background: #fff;
background: var(--white);
border-radius: 2px;
box-shadow: 11;
}
@ -90,10 +96,14 @@ class NodeManagement extends LitElement {
h3,
h4,
h5 {
color: #333;
color: var(--black);
font-weight: 400;
}
.sblack {
color: var(--black);
}
[hidden] {
display: hidden !important;
visibility: none !important;
@ -127,6 +137,7 @@ class NodeManagement extends LitElement {
};
this.nodeConfig = {};
this.nodeDomain = "";
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light';
}
render() {
@ -134,7 +145,7 @@ class NodeManagement extends LitElement {
<div id="node-management-page">
<div class="node-card">
<h2>Node management for: ${this.nodeDomain}</h2>
<span><br />Node has been online for: ${this.upTime}</span>
<span class="sblack"><br />Node has been online for: ${this.upTime}</span>
<br /><br />
<div id="minting">
@ -212,8 +223,7 @@ class NodeManagement extends LitElement {
render(html`<mwc-button class="red" ?disabled=${this.removeMintingAccountLoading} @click=${() => this.removeMintingAccount(data.item.publicKey)}><mwc-icon>create</mwc-icon>Remove</mwc-button>`, root)
}}></vaadin-grid-column>
</vaadin-grid>
${this.isEmptyArray(this.mintingAccounts) ? html` No minting accounts found for this node ` : ""}
${this.isEmptyArray(this.mintingAccounts) ? html`<span style="color: var(--black);">No minting accounts found for this node</span>` : ""}
</div>
<br />
@ -267,7 +277,7 @@ class NodeManagement extends LitElement {
}}></vaadin-grid-column>
</vaadin-grid>
${this.isEmptyArray(this.peers) ? html` Node has no connected peers ` : ""}
${this.isEmptyArray(this.peers) ? html`<span style="color: var(--black);">Node has no connected peers</span>` : ""}
</div>
<br />
</div>
@ -275,6 +285,113 @@ class NodeManagement extends LitElement {
`;
}
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
// Call updateMintingAccounts
this.updateMintingAccounts();
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)
}
// Calculate HH MM SS from Milliseconds...
const convertMsToTime = (milliseconds) => {
let day, hour, minute, seconds;
seconds = Math.floor(milliseconds / 1000);
minute = Math.floor(seconds / 60);
seconds = seconds % 60;
hour = Math.floor(minute / 60);
minute = minute % 60;
day = Math.floor(hour / 24);
hour = hour % 24;
if (isNaN(day)) {
return "offline";
}
return day + "d " + hour + "h " + minute + "m";
};
const getNodeUpTime = () => {
parentEpml
.request("apiCall", {
url: `/admin/uptime`,
})
.then((res) => {
this.upTime = "";
setTimeout(() => {
this.upTime = convertMsToTime(res);
}, 1);
});
setTimeout(getNodeUpTime, this.config.user.nodeSettings.pingInterval);
};
const updatePeers = () => {
parentEpml
.request("apiCall", {
url: `/peers`,
})
.then((res) => {
setTimeout(() => {
this.peers = res;
}, 1);
});
setTimeout(updatePeers, this.config.user.nodeSettings.pingInterval);
};
const getNodeConfig = () => {
parentEpml.request("getNodeConfig").then((res) => {
setTimeout(() => {
this.nodeConfig = res;
}, 1);
let myNode = window.parent.reduxStore.getState().app.nodeConfig
.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
this.nodeDomain = myNode.domain + ":" + myNode.port;
});
setTimeout(getNodeConfig, 1000);
};
let configLoaded = false;
parentEpml.ready().then(() => {
parentEpml.subscribe("config", async c => {
if (!configLoaded) {
setTimeout(getNodeUpTime, 1);
setTimeout(updatePeers, 1);
setTimeout(this.updateMintingAccounts, 1);
setTimeout(getNodeConfig, 1);
configLoaded = true;
}
this.config = JSON.parse(c);
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) this.clearSelection();
})
});
parentEpml.imReady();
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
forceSyncPeer(peerAddress, rowIndex) {
parentEpml
.request("apiCall", {
@ -403,99 +520,6 @@ class NodeManagement extends LitElement {
});
}
firstUpdated() {
// Call updateMintingAccounts
this.updateMintingAccounts();
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)
}
// Calculate HH MM SS from Milliseconds...
const convertMsToTime = (milliseconds) => {
let day, hour, minute, seconds;
seconds = Math.floor(milliseconds / 1000);
minute = Math.floor(seconds / 60);
seconds = seconds % 60;
hour = Math.floor(minute / 60);
minute = minute % 60;
day = Math.floor(hour / 24);
hour = hour % 24;
if (isNaN(day)) {
return "offline";
}
return day + "d " + hour + "h " + minute + "m";
};
const getNodeUpTime = () => {
parentEpml
.request("apiCall", {
url: `/admin/uptime`,
})
.then((res) => {
this.upTime = "";
setTimeout(() => {
this.upTime = convertMsToTime(res);
}, 1);
});
setTimeout(getNodeUpTime, this.config.user.nodeSettings.pingInterval);
};
const updatePeers = () => {
parentEpml
.request("apiCall", {
url: `/peers`,
})
.then((res) => {
setTimeout(() => {
this.peers = res;
}, 1);
});
setTimeout(updatePeers, this.config.user.nodeSettings.pingInterval);
};
const getNodeConfig = () => {
parentEpml.request("getNodeConfig").then((res) => {
setTimeout(() => {
this.nodeConfig = res;
}, 1);
let myNode = window.parent.reduxStore.getState().app.nodeConfig
.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
this.nodeDomain = myNode.domain + ":" + myNode.port;
});
setTimeout(getNodeConfig, 1000);
};
let configLoaded = false;
parentEpml.ready().then(() => {
parentEpml.subscribe("config", async c => {
if (!configLoaded) {
setTimeout(getNodeUpTime, 1);
setTimeout(updatePeers, 1);
setTimeout(this.updateMintingAccounts, 1);
setTimeout(getNodeConfig, 1);
configLoaded = true;
}
this.config = JSON.parse(c);
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) this.clearSelection();
})
});
parentEpml.imReady();
}
getApiKey() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
let apiKey = myNode.apiKey;

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -29,7 +29,8 @@ class Puzzles extends LitElement {
selectedAddress: { type: Object },
selectedPuzzle: { type: Object },
error: { type: Boolean },
message: { type: String }
message: { type: String },
theme: { type: String, reflect: true }
}
}
@ -43,9 +44,16 @@ class Puzzles extends LitElement {
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--lumo-secondary-text-color: var(--sectxt);
--lumo-contrast-60pct: var(--vdicon);
--_lumo-grid-border-color: var(--border);
--_lumo-grid-secondary-border-color: var(--border2);
}
#puzzle-page {
background: #fff;
background: var(--white);
padding: 12px 24px;
}
@ -54,7 +62,7 @@ class Puzzles extends LitElement {
}
h2, h3, h4, h5 {
color:#333;
color: var(--black);
font-weight: 400;
}
@ -66,6 +74,13 @@ class Puzzles extends LitElement {
font-family: "Lucida Console", "Courier New", monospace;
font-size: smaller;
}
.divCard {
border: 1px solid var(--border);
padding: 1em;
box-shadow: 0 .3px 1px 0 rgba(0,0,0,0.14), 0 1px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20);
margin-bottom: 2em;
}
`
}
@ -79,6 +94,7 @@ class Puzzles extends LitElement {
this.selectedPuzzle = {}
this.error = false
this.message = ''
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
@ -154,6 +170,11 @@ class Puzzles extends LitElement {
}
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
window.addEventListener("contextmenu", (event) => {
event.preventDefault();
this._textMenu(event)
@ -342,6 +363,16 @@ class Puzzles extends LitElement {
})
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
async guessPuzzle(puzzle) {
this.selectedPuzzle = puzzle
this.shadowRoot.getElementById("puzzleGuess").value = ''

View File

@ -19,7 +19,8 @@ class WebBrowser extends LitElement {
service: { type: String },
identifier: { type: String },
followedNames: { type: Array },
blockedNames: { type: Array }
blockedNames: { type: Array },
theme: { type: String, reflect: true }
}
}
@ -49,7 +50,7 @@ class WebBrowser extends LitElement {
left: 0;
right: 0;
height: 100px;
background-color: white;
background-color: var(--white);
height: 36px;
}
@ -63,7 +64,7 @@ class WebBrowser extends LitElement {
left: 0;
right: 0;
bottom: 0;
border-top: 1px solid #000000;
border-top: 1px solid var(--black);
}
.iframe-container iframe {
@ -71,7 +72,7 @@ class WebBrowser extends LitElement {
width: 100%;
height: 100%;
border: none;
background-color: #ffffff;
background-color: var(--white);
}
input[type=text] {
@ -80,7 +81,7 @@ class WebBrowser extends LitElement {
border: 0;
height: 34px;
font-size: 16px;
background-color: #ffffff;
background-color: var(--white);
}
paper-progress {
@ -94,23 +95,105 @@ class WebBrowser extends LitElement {
`
}
constructor() {
super()
this.url = 'about:blank'
const urlParams = new URLSearchParams(window.location.search);
this.name = urlParams.get('name');
this.service = urlParams.get('service');
// FUTURE: add support for identifiers
this.identifier = null;
this.followedNames = []
this.blockedNames = []
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
const getFollowedNames = async () => {
let followedNames = await parentEpml.request('apiCall', {
url: `/lists/followedNames?apiKey=${this.getApiKey()}`
})
this.followedNames = followedNames
setTimeout(getFollowedNames, this.config.user.nodeSettings.pingInterval)
}
const getBlockedNames = async () => {
let blockedNames = await parentEpml.request('apiCall', {
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`
})
this.blockedNames = blockedNames
setTimeout(getBlockedNames, this.config.user.nodeSettings.pingInterval)
}
const render = () => {
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.url = `${nodeUrl}/render/${this.service}/${this.name}`;
}
const authorizeAndRender = () => {
parentEpml.request('apiCall', {
url: `/render/authorize/${this.name}?apiKey=${this.getApiKey()}`,
method: "POST"
}).then(res => {
console.log(res)
if (res.error) {
// Authorization problem - API key incorrect?
}
else {
render()
}
})
}
let configLoaded = false
parentEpml.ready().then(() => {
parentEpml.subscribe('selected_address', async selectedAddress => {
this.selectedAddress = {}
selectedAddress = JSON.parse(selectedAddress)
if (!selectedAddress || Object.entries(selectedAddress).length === 0) return
this.selectedAddress = selectedAddress
})
parentEpml.subscribe('config', c => {
this.config = JSON.parse(c)
if (!configLoaded) {
authorizeAndRender()
setTimeout(getFollowedNames, 1)
setTimeout(getBlockedNames, 1)
configLoaded = true
}
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
})
}
render() {
return html`
<div id="websitesWrapper" style="width:auto; padding:10px; background: #fff;">
<div id="websitesWrapper" style="width:auto; padding:10px; background: var(--white);">
<div class="layout horizontal center">
<div class="address-bar">
<mwc-button @click=${() => this.goBack()} title="Back" class="address-bar-button"><mwc-icon>arrow_back_ios</mwc-icon></mwc-button>
<mwc-button @click=${() => this.goForward()} title="Forward" class="address-bar-button"><mwc-icon>arrow_forward_ios</mwc-icon></mwc-button>
<mwc-button @click=${() => this.refresh()} title="Reload" class="address-bar-button"><mwc-icon>refresh</mwc-icon></mwc-button>
<mwc-button @click=${() => this.goBackToList()} title="Back to list" class="address-bar-button"><mwc-icon>home</mwc-icon></mwc-button>
<input disabled style="width:550px;" id="address" type="text" value="qortal://${this.service.toLowerCase()}/${this.name}"></input>
<input disabled style="width: 550px; color: var(--black);" id="address" type="text" value="qortal://${this.service.toLowerCase()}/${this.name}"></input>
<mwc-button @click=${() => this.delete()} title="Delete ${this.service} ${this.name} from node" class="address-bar-button float-right"><mwc-icon>delete</mwc-icon></mwc-button>
${this.renderBlockUnblockButton()}
${this.renderFollowUnfollowButton()}
</div>
<div class="iframe-container">
<iframe id="browser-iframe" src="${this.url}" sandbox="allow-scripts allow-forms allow-downloads">
Your browser doesn't support iframes
<span style="color: var(--black);">Your browser doesn't support iframes</span>
</iframe>
</div>
</div>
@ -118,6 +201,38 @@ class WebBrowser extends LitElement {
`
}
firstUpdated() {
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)
}
}
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
renderFollowUnfollowButton() {
// Only show the follow/unfollow button if we have permission to modify the list on this node
if (this.followedNames == null || !Array.isArray(this.followedNames)) {
@ -357,105 +472,6 @@ class WebBrowser extends LitElement {
checkSelectedTextAndShowMenu()
}
constructor() {
super()
this.url = 'about:blank'
const urlParams = new URLSearchParams(window.location.search);
this.name = urlParams.get('name');
this.service = urlParams.get('service');
// FUTURE: add support for identifiers
this.identifier = null;
this.followedNames = []
this.blockedNames = []
const getFollowedNames = async () => {
let followedNames = await parentEpml.request('apiCall', {
url: `/lists/followedNames?apiKey=${this.getApiKey()}`
})
this.followedNames = followedNames
setTimeout(getFollowedNames, this.config.user.nodeSettings.pingInterval)
}
const getBlockedNames = async () => {
let blockedNames = await parentEpml.request('apiCall', {
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`
})
this.blockedNames = blockedNames
setTimeout(getBlockedNames, this.config.user.nodeSettings.pingInterval)
}
const render = () => {
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.url = `${nodeUrl}/render/${this.service}/${this.name}`;
}
const authorizeAndRender = () => {
parentEpml.request('apiCall', {
url: `/render/authorize/${this.name}?apiKey=${this.getApiKey()}`,
method: "POST"
}).then(res => {
console.log(res)
if (res.error) {
// Authorization problem - API key incorrect?
}
else {
render()
}
})
}
let configLoaded = false
parentEpml.ready().then(() => {
parentEpml.subscribe('selected_address', async selectedAddress => {
this.selectedAddress = {}
selectedAddress = JSON.parse(selectedAddress)
if (!selectedAddress || Object.entries(selectedAddress).length === 0) return
this.selectedAddress = selectedAddress
})
parentEpml.subscribe('config', c => {
this.config = JSON.parse(c)
if (!configLoaded) {
authorizeAndRender()
setTimeout(getFollowedNames, 1)
setTimeout(getBlockedNames, 1)
configLoaded = true
}
})
parentEpml.subscribe('copy_menu_switch', async value => {
if (value === 'false' && window.getSelection().toString().length !== 0) {
this.clearSelection()
}
})
})
}
firstUpdated() {
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)
}
}
}
getApiKey() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
let apiKey = myNode.apiKey;

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -21,7 +21,8 @@ class DataManagement extends LitElement {
searchDatres: { type: Array },
blockedNames: { type: Array },
followedNames: { type: Array },
datres: { type: Array }
datres: { type: Array },
theme: { type: String, reflect: true }
}
}
@ -34,6 +35,12 @@ class DataManagement extends LitElement {
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--lumo-secondary-text-color: var(--sectxt);
--lumo-contrast-60pct: var(--vdicon);
--_lumo-grid-border-color: var(--border);
--_lumo-grid-secondary-border-color: var(--border2);
}
#pages {
@ -53,6 +60,7 @@ class DataManagement extends LitElement {
font: inherit;
outline: none;
cursor: pointer;
color: var(--black);
}
#pages > button:not([disabled]):hover,
@ -63,7 +71,7 @@ class DataManagement extends LitElement {
#pages > button[selected] {
font-weight: bold;
color: white;
color: var(--white);
background-color: #ccc;
}
@ -73,7 +81,7 @@ class DataManagement extends LitElement {
}
#websites-list-page {
background: #fff;
background: var(--white);
padding: 12px 24px;
}
@ -84,7 +92,7 @@ class DataManagement extends LitElement {
}
.divCard {
border: 1px solid #eee;
border: 1px solid var(--border);
padding: 1em;
box-shadow: 0 .3px 1px 0 rgba(0,0,0,0.14), 0 1px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20);
margin-bottom: 2em;
@ -95,12 +103,12 @@ class DataManagement extends LitElement {
}
h2, h3, h4, h5 {
color:#333;
color: var(--black);
font-weight: 400;
}
a.visitSite {
color: #000;
color: var(--black);
text-decoration: none;
}
@ -155,6 +163,7 @@ class DataManagement extends LitElement {
this.followedNames = []
this.datres = []
this.isLoading = false
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
@ -218,6 +227,10 @@ class DataManagement extends LitElement {
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
this.showManagement()
window.addEventListener('contextmenu', (event) => {
@ -270,6 +283,16 @@ class DataManagement extends LitElement {
parentEpml.imReady()
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
searchListener(e) {
if (e.key === 'Enter') {
this.doSearch(e);

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -28,7 +28,7 @@ class PublishData extends LitElement {
metadata: { type: Array },
categories: { type: Array },
names: { type: Array },
registeredName: { type: String },
myRegisteredName: { type: String },
selectedName: { type: String },
path: { type: String },
portForwardingEnabled: { type: Boolean },
@ -465,7 +465,7 @@ class PublishData extends LitElement {
// Default to true so the message doesn't appear and disappear quickly
this.portForwardingEnabled = true
this.names = []
this.registeredName = ''
this.myRegisteredName = ''
this.selectedName = 'invalid'
this.path = ''
this.successMessage = ''
@ -482,7 +482,7 @@ class PublishData extends LitElement {
setTimeout(() => {
this.names = res
if (res[0] != null) {
this.registeredName = res[0].name;
this.myRegisteredName = res[0].name;
}
}, 1)
})
@ -509,7 +509,7 @@ class PublishData extends LitElement {
this.portForwardingEnabled = (res.inboundConnections != null && res.inboundConnections > 0);
}, 1)
})
setTimeout(fetchNames, this.config.user.nodeSettings.pingInterval)
setTimeout(fetchPeersSummary, this.config.user.nodeSettings.pingInterval)
}
let configLoaded = false

View File

@ -35,7 +35,8 @@ class Websites extends LitElement {
webBlockedNames: { type: Array },
blockResources: { type: Array },
blockFollowedNames: { type: Array },
blockBlockedNames: { type: Array }
blockBlockedNames: { type: Array },
theme: { type: String, reflect: true }
}
}
@ -48,6 +49,12 @@ class Websites extends LitElement {
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--lumo-secondary-text-color: var(--sectxt);
--lumo-contrast-60pct: var(--vdicon);
--_lumo-grid-border-color: var(--border);
--_lumo-grid-secondary-border-color: var(--border2);
}
#tabs-1 {
@ -59,6 +66,12 @@ class Websites extends LitElement {
padding-bottom: 10px;
}
mwc-tab-bar {
--mdc-text-transform: none;
--mdc-tab-color-default: var(--black);
--mdc-tab-text-label-color-default: var(--black);
}
#pages {
display: flex;
flex-wrap: wrap;
@ -76,6 +89,7 @@ class Websites extends LitElement {
font: inherit;
outline: none;
cursor: pointer;
color: var(--black);
}
#pages > button:not([disabled]):hover,
@ -86,7 +100,7 @@ class Websites extends LitElement {
#pages > button[selected] {
font-weight: bold;
color: white;
color: var(--white);
background-color: #ccc;
}
@ -96,7 +110,7 @@ class Websites extends LitElement {
}
#websites-list-page {
background: #fff;
background: var(--white);
padding: 12px 24px;
}
@ -107,7 +121,7 @@ class Websites extends LitElement {
}
.divCard {
border: 1px solid #eee;
border: 1px solid var(--border);
padding: 1em;
box-shadow: 0 .3px 1px 0 rgba(0,0,0,0.14), 0 1px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20);
margin-bottom: 2em;
@ -118,12 +132,12 @@ class Websites extends LitElement {
}
h2, h3, h4, h5 {
color:#333;
color: var(--black);
font-weight: 400;
}
a.visitSite {
color: #000;
color: var(--black);
text-decoration: none;
}
@ -186,7 +200,7 @@ class Websites extends LitElement {
word-break:normal;
font-size:14px;
line-height:20px;
color:rgb(100,100,100);
color: var(--relaynodetxt);
}
img {
@ -218,6 +232,7 @@ class Websites extends LitElement {
this.blockResources = []
this.blockFollowedNames = []
this.blockBlockedNames = []
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
@ -297,7 +312,7 @@ class Websites extends LitElement {
Loading...
`: ''}
${this.isEmptyArray(this.resources) ? html`
No websites available
<span style="color: var(--black);">No websites available</span>
`: ''}
</div>
${this.renderRelayModeText()}
@ -335,7 +350,7 @@ class Websites extends LitElement {
Loading...
`: ''}
${this.isEmptyArray(this.webResources) ? html`
You aren't following any websites
<span style="color: var(--black);">You aren't following any websites</span>
`: ''}
</div>
${this.renderRelayModeText()}
@ -373,7 +388,7 @@ class Websites extends LitElement {
Loading...
`: ''}
${this.isEmptyArray(this.blockResources) ? html`
You have not blocked any websites
<span style="color: var(--black);">You have not blocked any websites</span>
`: ''}
</div>
${this.renderRelayModeText()}
@ -385,6 +400,10 @@ class Websites extends LitElement {
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
this.showWebsites()
setTimeout(() => {
@ -526,6 +545,16 @@ class Websites extends LitElement {
parentEpml.imReady()
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
displayTabContent(tab) {
const tabBrowseContent = this.shadowRoot.getElementById('tab-browse-content')
const tabFollowedContent = this.shadowRoot.getElementById('tab-followed-content')

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -24,7 +24,8 @@ class RewardShare extends LitElement {
removeRewardShareLoading: { type: Boolean },
rewardSharePercentage: { type: Number },
error: { type: Boolean },
message: { type: String }
message: { type: String },
theme: { type: String, reflect: true }
}
}
@ -38,15 +39,24 @@ class RewardShare extends LitElement {
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--_lumo-grid-border-color: var(--border);
--_lumo-grid-secondary-border-color: var(--border2);
}
.myGridColor {
background-color: var(--white) !important;
color: var(--black);
}
#reward-share-page {
background: #fff;
background: var(--white);
padding: 12px 24px;
}
.divCard {
border: 1px solid #eee;
border: 1px solid var(--border);
padding: 1em;
box-shadow: 0 .3px 1px 0 rgba(0,0,0,0.14), 0 1px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20);
}
@ -56,7 +66,7 @@ class RewardShare extends LitElement {
}
h2, h3, h4, h5 {
color:#333;
color: var(--black);
font-weight: 400;
}
@ -75,6 +85,7 @@ class RewardShare extends LitElement {
this.btnDisable = false
this.createRewardShareLoading = false
this.removeRewardShareLoading = false
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
@ -87,7 +98,7 @@ class RewardShare extends LitElement {
<div class="divCard">
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">Rewardshares Involving In This Account</h3>
<vaadin-grid theme="large" id="accountRewardSharesGrid" ?hidden="${this.isEmptyArray(this.rewardShares)}" .items="${this.rewardShares}" all-rows-visible>
<vaadin-grid id="accountRewardSharesGrid" ?hidden="${this.isEmptyArray(this.rewardShares)}" .items="${this.rewardShares}" all-rows-visible>
<vaadin-grid-column auto-width path="mintingAccount"></vaadin-grid-column>
<vaadin-grid-column auto-width path="sharePercent"></vaadin-grid-column>
<vaadin-grid-column auto-width path="recipient"></vaadin-grid-column>
@ -146,13 +157,18 @@ class RewardShare extends LitElement {
</mwc-button>
</mwc-dialog>
${this.isEmptyArray(this.rewardShares) ? html`
Account is not involved in any reward shares
<span style="color: var(--black);">Account is not involved in any reward shares</span>
`: ''}
</div>
`
}
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
window.addEventListener("contextmenu", (event) => {
event.preventDefault();
this._textMenu(event)
@ -246,6 +262,16 @@ class RewardShare extends LitElement {
})
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
renderRemoveRewardShareButton(rewardShareObject) {
if (rewardShareObject.mintingAccount === this.selectedAddress.address) {
return html`<mwc-button class="red" ?disabled=${this.removeRewardShareLoading} @click=${() => this.removeRewardShare(rewardShareObject)}><mwc-icon>create</mwc-icon>Remove</mwc-button>`

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -29,7 +29,8 @@ class SendMoneyPage extends LitElement {
ltcBalance: { type: Number },
dogeBalance: { type: Number },
selectedCoin: { type: String },
satFeePerByte: { type: Number }
satFeePerByte: { type: Number },
theme: { type: String, reflect: true }
}
}
@ -45,6 +46,14 @@ class SendMoneyPage extends LitElement {
--paper-input-container-focus-color: var(--mdc-theme-primary);
}
h2,
h3,
h4,
h5 {
color: var(--black);
font-weight: 400;
}
#sendMoneyWrapper {
}
@ -80,6 +89,10 @@ class SendMoneyPage extends LitElement {
padding: 8px;
}
.baltxt {
color: var(--black);
}
mwc-textfield {
margin: 0;
}
@ -158,6 +171,7 @@ class SendMoneyPage extends LitElement {
this.ltcBalance = 0
this.dogeBalance = 0
this.selectedCoin = 'invalid'
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light';
let configLoaded = false
parentEpml.ready().then(() => {
@ -193,15 +207,14 @@ class SendMoneyPage extends LitElement {
render() {
return html`
<div id="sendMoneyWrapper" style="width:auto; padding:10px; background: #fff; height:100vh;">
<div id="sendMoneyWrapper" style="width:auto; padding:10px; background: var(--white); height:100vh;">
<div class="layout horizontal center" style="padding:12px 15px;">
<paper-card style="width:100%; max-width:740px;">
<div style="background-color: ${this.selectedAddress.color}; margin:0; color: ${this.textColor(this.selectedAddress.textColor)};">
<h3 style="margin: 0; padding: 8px 0;">Send Coin</h3>
<div class="selectedBalance">
<span id="balance"></span> available for transfer from
<span id="address"></span>
<span id="balance" class="baltxt"></span> <span class="baltxt">available for transfer from</span> <span id="address" class="baltxt"></span>
</div>
</div>
</paper-card>
@ -231,7 +244,7 @@ class SendMoneyPage extends LitElement {
</p>
<div style="${this.selectedCoin === 'invalid' || this.selectedCoin === 'qort' ? 'visibility: hidden; margin-bottom: -5em;' : 'visibility: visible; margin-bottom: 0;'}">
<p style="margin-bottom:0;">Fee per byte: ${(this.satFeePerByte / 1e8).toFixed(8)} ${this.selectedCoin === 'invalid' ? 'QORT' : this.selectedCoin.toLocaleUpperCase()}</p>
<p style="margin-bottom: 0; color: var(--black);">Fee per byte: ${(this.satFeePerByte / 1e8).toFixed(8)} ${this.selectedCoin === 'invalid' ? 'QORT' : this.selectedCoin.toLocaleUpperCase()}</p>
<mwc-slider
@change="${(e) => (this.satFeePerByte = e.target.value)}"
id="feeSlider"
@ -245,7 +258,7 @@ class SendMoneyPage extends LitElement {
</mwc-slider>
</div>
<p style="color:red">${this.errorMessage}</p>
<p style="color: red;">${this.errorMessage}</p>
<p style="color: green; word-break: break-word;">${this.successMessage}</p>
${this.sendMoneyLoading ? html` <paper-progress indeterminate style="width:100%; margin:4px;"></paper-progress> ` : ''}
@ -261,6 +274,11 @@ class SendMoneyPage extends LitElement {
}
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
// Get BTC Balance
this.updateBTCAccountBalance()
@ -270,6 +288,14 @@ class SendMoneyPage extends LitElement {
// Get DOGE Balance
this.updateDOGEAccountBalance()
setInterval(() => {
this.errorMessage = '';
}, 5000)
setInterval(() => {
this.successMessage = '';
}, 5000)
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
this._textMenu(event)
@ -339,6 +365,16 @@ class SendMoneyPage extends LitElement {
})
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
_floor(num) {
return Math.floor(num)
}
@ -561,7 +597,6 @@ class SendMoneyPage extends LitElement {
throw new Error(txnResponse)
}
}
validateReceiver(recipient)
}

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -34,7 +34,8 @@ class TradePortal extends LitElement {
selectedCoin: { type: String },
isLoadingHistoricTrades: { type: Boolean },
isLoadingOpenTrades: { type: Boolean },
isLoadingMyOpenOrders: { type: Boolean }
isLoadingMyOpenOrders: { type: Boolean },
theme: { type: String, reflect: true }
}
}
@ -43,18 +44,40 @@ 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-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-hover-border-color: var(--txtfieldhoverborder);
--mdc-select-label-ink-color: var(--black);
--mdc-select-ink-color: var(--black);
--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);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--lumo-secondary-text-color: var(--sectxt);
--lumo-contrast-60pct: var(--vdicon);
--_lumo-grid-border-color: var(--border);
--_lumo-grid-secondary-border-color: var(--border2);
}
mwc-tab-bar {
--mdc-text-transform: none;
--mdc-tab-color-default: var(--black);
--mdc-tab-text-label-color-default: var(--black);
}
#tabs-1 {
--mdc-tab-height: 50px;
border-left: 1px solid rgb(102, 102, 102);
border-top: 1px solid rgb(102, 102, 102);
border-right: 1px solid rgb(102, 102, 102);
border-left: 1px solid var(--tradeborder);
border-top: 1px solid var(--tradeborder);
border-right: 1px solid var(--tradeborder);
color: var(--black);
}
#tab-buy[active] {
@ -68,7 +91,7 @@ class TradePortal extends LitElement {
#tabs-1-content > div {
height: 100%;
border: 1px solid rgb(102, 102, 102);
border: 1px solid var(--tradeborder);
}
#tabs-1-content .card {
@ -77,6 +100,7 @@ class TradePortal extends LitElement {
#tabs-1-content .btn-clear {
--mdc-icon-button-size: 40px;
color: var(--black);
}
#tab-sell[active] {
@ -84,12 +108,12 @@ class TradePortal extends LitElement {
}
#trade-portal-page {
background: #fff;
background: var(--white);
padding: 12px 24px;
}
.divCard {
border: 1px solid #eee;
border: 1px solid var(--black);
padding: 1em;
box-shadow: 0 0.3px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 1px -1px rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.2);
}
@ -102,7 +126,7 @@ class TradePortal extends LitElement {
h3,
h4,
h5 {
color: #333;
color: var(--black);
font-weight: 400;
}
@ -113,8 +137,11 @@ class TradePortal extends LitElement {
justify-content: center;
padding: 0px 15px;
font-size: 16px;
color: #fff;
background-color: rgb(106, 108, 117);
color: var(--white);
background-color: var(--tradehead);
border-left: 1px solid var(--tradeborder);
border-top: 1px solid var(--tradeborder);
border-right: 1px solid var(--tradeborder);
min-height: 40px;
}
@ -158,7 +185,7 @@ class TradePortal extends LitElement {
}
.trade-chart {
background-color: #eee;
background-color: var(--white);
border: 2px #ddd solid;
text-align: center;
}
@ -184,7 +211,7 @@ class TradePortal extends LitElement {
.card {
padding: 1em;
border: 1px #666 solid;
border: 1px var(--tradeborder) solid;
flex: 1 1 auto;
display: flex;
flex-flow: column;
@ -197,12 +224,12 @@ class TradePortal extends LitElement {
}
.border-wrapper {
border: 1px #666 solid;
border: 1px var(--tradeborder) solid;
overflow: hidden;
}
.you-have {
color: #555;
color: var(--tradehave);
font-size: 15px;
text-align: right;
margin-top: 2px;
@ -234,7 +261,7 @@ class TradePortal extends LitElement {
}
.full-width {
background-color: #fff;
background-color: var(--white);
border: 2px #ddd solid;
height: 100px;
text-align: center;
@ -435,6 +462,7 @@ class TradePortal extends LitElement {
this.isLoadingHistoricTrades = true
this.isLoadingOpenTrades = true
this.isLoadingMyOpenOrders = false
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
// TODO: Move each template to a separate components! Maybe
@ -544,7 +572,7 @@ class TradePortal extends LitElement {
</div>
<p>
<mwc-textfield
style="width:100%;"
style="width: 100%; color: var(--black);"
id="buyAmountInput"
required readOnly label="Amount (QORT)"
placeholder="0.0000"
@ -556,7 +584,7 @@ class TradePortal extends LitElement {
</p>
<p>
<mwc-textfield
style="width:100%;"
style="width: 100%; color: var(--black);"
id="buyPriceInput"
required readOnly
label="Price Ea. (${this.listedCoins.get(this.selectedCoin).coinCode})"
@ -569,7 +597,7 @@ class TradePortal extends LitElement {
</p>
<p style="margin-bottom: 10px;">
<mwc-textfield
style="width:100%;"
style="width: 100%; color: var(--black);"
id="buyTotalInput"
required readOnly
label="Total (${this.listedCoins.get(this.selectedCoin).coinCode})"
@ -607,7 +635,7 @@ class TradePortal extends LitElement {
</div>
<p>
<mwc-textfield
style="width:100%;"
style="width: 100%; color: var(--black);"
id="sellAmountInput"
required label="Amount (QORT)"
placeholder="0.0000"
@ -620,7 +648,7 @@ class TradePortal extends LitElement {
</p>
<p>
<mwc-textfield
style="width:100%;"
style="width: 100%; color: var(--black);"
id="sellPriceInput"
required label="Price Ea. (${this.listedCoins.get(this.selectedCoin).coinCode})"
placeholder="0.0000"
@ -633,7 +661,7 @@ class TradePortal extends LitElement {
</p>
<p style="margin-bottom: 10px;">
<mwc-textfield
style="width:100%;"
style="width: 100%; color: var(--black);"
id="sellTotalInput"
required readOnly
label="Total (${this.listedCoins.get(this.selectedCoin).coinCode})"
@ -829,6 +857,10 @@ class TradePortal extends LitElement {
firstUpdated() {
let _this = this
setInterval(() => {
this.changeTheme();
}, 100)
this.updateWalletBalance()
setTimeout(() => {
@ -907,6 +939,16 @@ class TradePortal extends LitElement {
setTimeout(() => this.shadowRoot.querySelector('[slot="vaadin-grid-cell-content-3"]').setAttribute('title', 'Last Seen'), 3000)
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
updateWalletBalance() {
let _url = ``
let _body = null

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style>
html {
--scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body {
margin: 0;
font-family: "Roboto", sans-serif;
background-color: #fff;
background: var(--plugback);
}
</style>
</head>

View File

@ -24,6 +24,7 @@ class MultiWallet extends LitElement {
isTextMenuOpen: { type: Boolean },
wallets: { type: Map },
_selectedWallet: 'qort',
theme: { type: String, reflect: true },
balanceString: 'Fetching balance ...'
}
}
@ -37,6 +38,10 @@ class MultiWallet extends LitElement {
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--_lumo-grid-border-color: var(--border);
--_lumo-grid-secondary-border-color: var(--border2);
}
#pages {
@ -56,6 +61,7 @@ class MultiWallet extends LitElement {
font: inherit;
outline: none;
cursor: pointer;
color: var(--black);
}
#pages > button:not([disabled]):hover,
@ -66,7 +72,7 @@ class MultiWallet extends LitElement {
#pages > button[selected] {
font-weight: bold;
color: white;
color: var(--white);
background-color: #ccc;
}
@ -108,7 +114,7 @@ class MultiWallet extends LitElement {
.text-white-primary {
color: var(--white-primary);
color: var(--white);
}
.text-white-secondary {
@ -124,6 +130,7 @@ class MultiWallet extends LitElement {
table {
border: none;
}
table td,
th {
white-space: nowrap;
@ -131,39 +138,51 @@ class MultiWallet extends LitElement {
font-size: 14px;
padding: 0 12px;
font-family: 'Roboto', sans-serif;
color: var(--black);
background: var(--white);
}
table tr {
height: 48px;
}
table tr:hover td {
background: #eee;
}
table tr th {
color: #666;
font-size: 12px;
}
table tr td {
margin: 0;
}
.white-bg {
height: 100vh;
background: #fff;
background: var(--white);
}
span {
font-size: 18px;
word-break: break-all;
}
.title {
font-weight: 600;
font-size: 12px;
line-height: 32px;
opacity: 0.66;
}
#transactionList {
padding: 0;
}
#transactionList > * {
}
.color-in {
color: #02977e;
background-color: rgba(0, 201, 167, 0.2);
@ -173,6 +192,7 @@ class MultiWallet extends LitElement {
padding: 0.2rem 0.5rem;
margin-left: 4px;
}
.color-out {
color: #b47d00;
background-color: rgba(219, 154, 4, 0.2);
@ -186,7 +206,7 @@ class MultiWallet extends LitElement {
body {
margin: 0;
padding: 0;
background: white;
background: var(--white);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@ -194,7 +214,7 @@ class MultiWallet extends LitElement {
h2 {
margin: 0;
font-weight: 400;
color: #707584;
color: var(--black);
font: 24px/24px 'Open Sans', sans-serif;
}
@ -218,7 +238,7 @@ class MultiWallet extends LitElement {
height: 100%;
overflow: hidden;
border-radius: 8px;
background-color: #fff;
background-color: var(--white);
}
.wallet {
@ -226,7 +246,7 @@ class MultiWallet extends LitElement {
height: 100vh;
border-top-left-radius: inherit;
border-bottom-left-radius: inherit;
border-right: 1px solid #eee;
border-right: 1px solid var(--border);
}
.transactions-wrapper {
@ -243,7 +263,7 @@ class MultiWallet extends LitElement {
display: flex;
align-items: center;
font-size: 18px;
color: var(--mdc-theme-primary, #444750);
color: var(--black);
margin: 4px 0 20px;
}
@ -251,14 +271,14 @@ class MultiWallet extends LitElement {
display: inline-block;
font-weight: 600;
font-size: 32px;
color: var(--mdc-theme-primary, #444750);
color: var(--black);
}
#transactions {
margin-top: 60px;
margin-left: 20px;
margin-right: 20px;
border-top: 1px solid #e5e5e5;
border-top: 1px solid var(--border);
padding-top: 0px;
height: 100%;
}
@ -275,6 +295,7 @@ class MultiWallet extends LitElement {
margin-bottom: 45px;
margin-right: 50px;
}
.transaction-item::before {
position: absolute;
content: '';
@ -324,18 +345,19 @@ class MultiWallet extends LitElement {
.currency-box {
display: flex;
background-color: #fff;
background-color: var(--white);
text-align: center;
padding: 12px;
cursor: pointer;
transition: 0.1s ease-in-out;
}
.currency-box:not(:last-child) {
border-bottom: 1px solid #eee;
border-bottom: var(--border);
}
.active {
background: #ddd;
background: var(--menuactive);
}
.currency-image {
@ -347,13 +369,16 @@ class MultiWallet extends LitElement {
border-radius: 3px;
filter: grayscale(100%);
}
.currency-box.active .currency-image,
.currency-box:hover .currency-image {
filter: none;
}
.currency-box:hover {
background: #bbb;
background: var(--menuhover);
}
.currency-box.active,
.currency-box:hover .currency-text {
font-weight: 500;
@ -363,7 +388,7 @@ class MultiWallet extends LitElement {
margin: auto 0;
margin-left: 8px;
font-size: 20px;
color: #777;
color: var(--black);
}
.qort .currency-image {
@ -496,6 +521,8 @@ class MultiWallet extends LitElement {
this.selectWallet = this.selectWallet.bind(this)
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light';
this.wallets = new Map()
let coinProp = {
balance: 0,
@ -539,7 +566,7 @@ class MultiWallet extends LitElement {
return html`
<div class="wrapper">
<div class="wallet">
<div style="font-size: 20px; color: #777; padding: 16px; border-bottom: 1px solid #eee;">Wallets</div>
<div style="font-size: 20px; color: var(--black); padding: 16px; border-bottom: 1px solid var(--border);">Wallets</div>
<div class="cards">
<div coin="qort" class="currency-box qort active">
<div class="currency-image"></div>
@ -572,7 +599,7 @@ class MultiWallet extends LitElement {
textToCopy=${this.getSelectedWalletAddress()}
buttonSize="28px"
iconSize="16px"
color="#707584"
color="var(--copybutton)"
offsetLeft="4px"
>
</button-icon-copy>
@ -631,13 +658,167 @@ class MultiWallet extends LitElement {
`
}
firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
// DOM refs
this.currencyBoxes = this.shadowRoot.querySelectorAll('.currency-box')
this.transactionsDOM = this.shadowRoot.getElementById('transactionsDOM')
// Attach eventlisteners to the cuurency boxes
this.currencyBoxes.forEach((currencyBox) => {
currencyBox.addEventListener('click', this.selectWallet)
})
this.showWallet()
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
this.isTextMenuOpen = true
this._textMenu(event)
})
window.addEventListener('click', () => {
if (this.isTextMenuOpen) {
parentEpml.request('closeCopyTextMenu', null)
}
})
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
}
}
selectWallet(event) {
event.preventDefault()
const target = event.currentTarget
// if (target.classList.contains('active')) return
// removed to allow one click wallet refresh
this.currencyBoxes.forEach((currencyBox) => {
if (currencyBox.classList.contains('active')) {
currencyBox.classList.remove('active')
}
})
target.classList.add('active')
this._selectedWallet = target.attributes.coin.value
this.showWallet()
}
async showWallet() {
this.transactionsDOM.hidden = true
this.loading = true
if (this._selectedWallet == 'qort') {
if (!window.parent.reduxStore.getState().app.blockInfo.height) {
// we make sure that `blockHeight` is set before rendering QORT transactions
await parentEpml.request('apiCall', { url: `/blocks/height`, type: 'api' })
.then(height => parentEpml.request('updateBlockInfo', { height }))
}
}
const coin = this._selectedWallet
await this.fetchWalletDetails(this._selectedWallet)
if (this._selectedWallet == coin) {
//if the wallet didn't switch
await this.renderTransactions()
await this.getTransactionGrid(this._selectedWallet)
await this.updateItemsFromPage(1, true)
this.loading = false
this.transactionsDOM.hidden = false
}
}
async fetchWalletDetails(coin) {
//this function will fetch the balance and transactions of the given wallet
this.balanceString = "Fetching balance ..."
switch (coin) {
case 'qort':
//fetching the qort balance
parentEpml
.request('apiCall', {
url: `/addresses/balance/${this.wallets.get('qort').wallet.address}?apiKey=${this.getApiKey()}`,
})
.then((res) => {
if (isNaN(Number(res))) {
parentEpml.request('showSnackBar', `Failed to Fetch QORT Balance. Try again!`)
} else {
if (this._selectedWallet == coin) {
//check if we are still fetching wallet balance ...
this.wallets.get(coin).balance = res
this.balanceString = this.wallets.get(this._selectedWallet).balance + " " + this._selectedWallet.toLocaleUpperCase()
}
}
})
//fetching the qort transactions
const txsQort = await parentEpml.request('apiCall', {
url: `/transactions/search?address=${this.wallets.get('qort').wallet.address}&confirmationStatus=CONFIRMED&reverse=true`,
})
if (this._selectedWallet == coin)
this.wallets.get(coin).transactions = txsQort
break
case 'btc':
case 'ltc':
case 'doge':
//fetching the balance
const walletName = `${coin}Wallet`
parentEpml
.request('apiCall', {
url: `/crosschain/${coin}/walletbalance?apiKey=${this.getApiKey()}`,
method: 'POST',
body: `${window.parent.reduxStore.getState().app.selectedAddress[walletName].derivedMasterPublicKey}`,
})
.then((res) => {
if (isNaN(Number(res))) {
parentEpml.request('showSnackBar', `Failed to Fetch ${coin.toLocaleUpperCase()} Balance. Try again!`)
} else {
if (this._selectedWallet == coin) {
//check if we are still fetching wallet balance ...
this.wallets.get(this._selectedWallet).balance = (Number(res) / 1e8).toFixed(8)
this.balanceString = this.wallets.get(this._selectedWallet).balance + " " + this._selectedWallet.toLocaleUpperCase()
}
}
})
//fetching transactions
const txs = await parentEpml.request('apiCall', {
url: `/crosschain/${coin}/wallettransactions?apiKey=${this.getApiKey()}`,
method: 'POST',
body: `${window.parent.reduxStore.getState().app.selectedAddress[walletName].derivedMasterPublicKey}`,
})
const compareFn = (a, b) => {
return b.timestamp - a.timestamp
}
const sortedTransactions = txs.sort(compareFn)
if (this._selectedWallet == coin) {
this.wallets.get(this._selectedWallet).transactions = sortedTransactions
}
break
default:
break
}
}
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
document.querySelector('html').setAttribute('theme', this.theme);
}
getSelectedWalletAddress() {
return this._selectedWallet === 'qort'
? this.wallets.get(this._selectedWallet).wallet.address
: this.wallets.get(this._selectedWallet).wallet.address
}
async getTransactionGrid(coin) {
this.transactionsGrid = this.shadowRoot.querySelector(`#${coin}TransactionsGrid`)
if (coin === 'qort') {
@ -675,19 +856,7 @@ class MultiWallet extends LitElement {
}
return html`
<dom-module id="vaadin-grid-qort-theme" theme-for="vaadin-grid">
<template>
<style>
:host([theme~="qort"]) table thead tr > th:first-of-type,
:host([theme~="qort"]) table tbody tr > td:first-of-type {
min-width: 56px;
max-width: 56px;
padding: 4px 0;
}
</style>
</template>
</dom-module>
<div style="padding-left:12px;" ?hidden="${!this.isEmptyArray(transactions)}">Address has no transactions yet.</div>
<div style="padding-left:12px;" ?hidden="${!this.isEmptyArray(transactions)}"><span style="color: var(--black);">Address has no transactions yet.</span></div>
<vaadin-grid theme="large" id="${coin}TransactionsGrid" ?hidden="${this.isEmptyArray(this.wallets.get(this._selectedWallet).transactions)}" page-size="25" all-rows-visible>
<vaadin-grid-column
auto-width
@ -734,7 +903,7 @@ class MultiWallet extends LitElement {
renderBTCLikeTransactions(transactions, coin) {
return html`
<div style="padding-left:12px;" ?hidden="${!this.isEmptyArray(transactions)}">Address has no transactions yet.</div>
<div style="padding-left:12px;" ?hidden="${!this.isEmptyArray(transactions)}"><span style="color: var(--black);">Address has no transactions yet.</span></div>
<vaadin-grid theme="large" id="${coin}TransactionsGrid" ?hidden="${this.isEmptyArray(this.wallets.get(this._selectedWallet).transactions)}" page-size="25" all-rows-visible>
<vaadin-grid-column auto-width resizable header="Transaction Hash" path="txHash"></vaadin-grid-column>
<vaadin-grid-column
@ -880,146 +1049,6 @@ class MultiWallet extends LitElement {
`
}
firstUpdated() {
// DOM refs
this.currencyBoxes = this.shadowRoot.querySelectorAll('.currency-box')
this.transactionsDOM = this.shadowRoot.getElementById('transactionsDOM')
// Attach eventlisteners to the cuurency boxes
this.currencyBoxes.forEach((currencyBox) => {
currencyBox.addEventListener('click', this.selectWallet)
})
this.showWallet()
window.addEventListener('contextmenu', (event) => {
event.preventDefault()
this.isTextMenuOpen = true
this._textMenu(event)
})
window.addEventListener('click', () => {
if (this.isTextMenuOpen) {
parentEpml.request('closeCopyTextMenu', null)
}
})
window.onkeyup = (e) => {
if (e.keyCode === 27) {
parentEpml.request('closeCopyTextMenu', null)
}
}
}
selectWallet(event) {
event.preventDefault()
const target = event.currentTarget
// if (target.classList.contains('active')) return
// removed to allow one click wallet refresh
this.currencyBoxes.forEach((currencyBox) => {
if (currencyBox.classList.contains('active')) {
currencyBox.classList.remove('active')
}
})
target.classList.add('active')
this._selectedWallet = target.attributes.coin.value
this.showWallet()
}
async showWallet() {
this.transactionsDOM.hidden = true
this.loading = true
if (this._selectedWallet == 'qort') {
if (!window.parent.reduxStore.getState().app.blockInfo.height) {
// we make sure that `blockHeight` is set before rendering QORT transactions
await parentEpml.request('apiCall', { url: `/blocks/height`, type: 'api' })
.then(height => parentEpml.request('updateBlockInfo', { height }))
}
}
const coin = this._selectedWallet
await this.fetchWalletDetails(this._selectedWallet)
if (this._selectedWallet == coin) {
//if the wallet didn't switch
await this.renderTransactions()
await this.getTransactionGrid(this._selectedWallet)
await this.updateItemsFromPage(1, true)
this.loading = false
this.transactionsDOM.hidden = false
}
}
async fetchWalletDetails(coin) {
//this function will fetch the balance and transactions of the given wallet
this.balanceString = "Fetching balance ..."
switch (coin) {
case 'qort':
//fetching the qort balance
parentEpml
.request('apiCall', {
url: `/addresses/balance/${this.wallets.get('qort').wallet.address}?apiKey=${this.getApiKey()}`,
})
.then((res) => {
if (isNaN(Number(res))) {
parentEpml.request('showSnackBar', `Failed to Fetch QORT Balance. Try again!`)
} else {
if (this._selectedWallet == coin) {
//check if we are still fetching wallet balance ...
this.wallets.get(coin).balance = res
this.balanceString = this.wallets.get(this._selectedWallet).balance + " " + this._selectedWallet.toLocaleUpperCase()
}
}
})
//fetching the qort transactions
const txsQort = await parentEpml.request('apiCall', {
url: `/transactions/search?address=${this.wallets.get('qort').wallet.address}&confirmationStatus=CONFIRMED&reverse=true`,
})
if (this._selectedWallet == coin)
this.wallets.get(coin).transactions = txsQort
break
case 'btc':
case 'ltc':
case 'doge':
//fetching the balance
const walletName = `${coin}Wallet`
parentEpml
.request('apiCall', {
url: `/crosschain/${coin}/walletbalance?apiKey=${this.getApiKey()}`,
method: 'POST',
body: `${window.parent.reduxStore.getState().app.selectedAddress[walletName].derivedMasterPublicKey}`,
})
.then((res) => {
if (isNaN(Number(res))) {
parentEpml.request('showSnackBar', `Failed to Fetch ${coin.toLocaleUpperCase()} Balance. Try again!`)
} else {
if (this._selectedWallet == coin) {
//check if we are still fetching wallet balance ...
this.wallets.get(this._selectedWallet).balance = (Number(res) / 1e8).toFixed(8)
this.balanceString = this.wallets.get(this._selectedWallet).balance + " " + this._selectedWallet.toLocaleUpperCase()
}
}
})
//fetching transactions
const txs = await parentEpml.request('apiCall', {
url: `/crosschain/${coin}/wallettransactions?apiKey=${this.getApiKey()}`,
method: 'POST',
body: `${window.parent.reduxStore.getState().app.selectedAddress[walletName].derivedMasterPublicKey}`,
})
const compareFn = (a, b) => {
return b.timestamp - a.timestamp
}
const sortedTransactions = txs.sort(compareFn)
if (this._selectedWallet == coin) {
this.wallets.get(this._selectedWallet).transactions = sortedTransactions
}
break
default:
break
}
}
showTransactionDetails(myTransaction, allTransactions) {
allTransactions.forEach((transaction) => {
if (myTransaction.signature === transaction.signature) {