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

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'
@ -27,47 +28,56 @@ class AppView extends connect(store)(LitElement) {
static get styles() {
return [
css`
: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);
}
app-header {
box-shadow: var(--shadow-2);
}
app-toolbar {
background: var(--mdc-theme-surface);
color: var(--mdc-theme-on-surface);
}
#sideBar {
height: 100vh;
display: flex;
flex-direction: column;
}
.sideBarMenu{
overflow-y: auto;
flex: 1 1;
}
#sideBar::-webkit-scrollbar {
width: 7px;
background-color: transparent;
}
:host {
--app-drawer-width: 260px;
}
#sideBar::-webkit-scrollbar-track {
background-color: transparent;
}
app-drawer-layout:not([narrow]) [drawer-toggle]:not(sidenav-menu) {
display: none;
}
#sideBar::-webkit-scrollbar-thumb {
background-color: #333;
border-radius: 6px;
border: 3px solid #333;
}
`
app-drawer {
box-shadow: var(--shadow-2);
background: var(--white);
}
app-header {
box-shadow: var(--shadow-2);
}
app-toolbar {
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;
}
#sideBar::-webkit-scrollbar-track {
background-color: transparent;
}
#sideBar::-webkit-scrollbar-thumb {
background-color: #333;
border-radius: 6px;
border: 3px solid #333;
}
`
]
}
@ -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

@ -15,12 +15,17 @@ class SecurityView extends connect(store)(LitElement) {
static get styles() {
return css`
* {
* {
--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);
}
.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,21 +153,24 @@ 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;
border: 0;
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,12 +140,13 @@ 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() {
return html`
<div id="group-management-page">
<div style="min-height:48px; display: flex; padding-bottom: 6px; margin: 2px;">
<div style="min-height: 48px; display: flex; padding-bottom: 6px; margin: 2px;">
<h2 style="margin: 0; flex: 1; padding-top: .1em; display: inline;">Qortal Groups</h2>
<mwc-button style="float:right;" @click=${() => this.shadowRoot.querySelector('#createGroupDialog').show()}><mwc-icon>add</mwc-icon>Create Group</mwc-button>
</div>
@ -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>
@ -182,7 +190,7 @@ class GroupManagement extends LitElement {
<hr>
</div>
<mwc-textfield style="width:100%;" ?disabled="${this.isLoading}" label="Group Name" id="groupNameInput"></mwc-textfield>
<mwc-textfield style="width: 100%;" ?disabled="${this.isLoading}" label="Group Name" id="groupNameInput"></mwc-textfield>
<p style="margin-bottom:0;">
<mwc-textfield style="width:100%;" ?disabled="${this.isLoading}" label="Description" id="groupDescInput"></mwc-textfield>
</p>
@ -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() {
@ -238,10 +240,10 @@ class MintingInfo extends LitElement {
</div>
<div>
<h3>Introduction</h3><br />
To "activate" your account, an OUTGOING transaction needs to take place.
Name Registration is the most common method. You can ask someone in Q-Chat to send you a small amount of QORT so that you may activate your account,
or buy QORT within the Trade Portal then make an OUTGOING transaction of any kind and secure your public key on the blockchain.
Until you do this, your public key is only known by you, in your UI, and no one else can pull your public key from the chain.
To "activate" your account, an OUTGOING transaction needs to take place.
Name Registration is the most common method. You can ask someone in Q-Chat to send you a small amount of QORT so that you may activate your account,
or buy QORT within the Trade Portal then make an OUTGOING transaction of any kind and secure your public key on the blockchain.
Until you do this, your public key is only known by you, in your UI, and no one else can pull your public key from the chain.
</div>
<mwc-button slot="primaryAction" dialogAction="cancel" class="red-button">Close</mwc-button>
</mwc-dialog>
@ -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,12 +35,18 @@ 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 {
#pages {
display: flex;
flex-wrap: wrap;
padding: 10px 5px 5px 5px;
padding: 10px 5px 5px 5px;
margin: 0px 20px 20px 20px;
}
@ -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,10 +66,16 @@ class Websites extends LitElement {
padding-bottom: 10px;
}
#pages {
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;
padding: 10px 5px 5px 5px;
padding: 10px 5px 5px 5px;
margin: 0px 20px 20px 20px;
}
@ -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 }
}
}
@ -39,99 +40,111 @@ class SendMoneyPage extends LitElement {
static get styles() {
return css`
* {
--mdc-theme-primary: rgb(3, 169, 244);
--mdc-theme-secondary: var(--mdc-theme-primary);
--paper-input-container-focus-color: var(--mdc-theme-primary);
}
* {
--mdc-theme-primary: rgb(3, 169, 244);
--mdc-theme-secondary: var(--mdc-theme-primary);
--paper-input-container-focus-color: var(--mdc-theme-primary);
}
#sendMoneyWrapper {
}
h2,
h3,
h4,
h5 {
color: var(--black);
font-weight: 400;
}
#sendMoneyWrapper paper-button {
float: right;
}
#sendMoneyWrapper {
}
#sendMoneyWrapper .buttons {
width: auto !important;
}
#sendMoneyWrapper paper-button {
float: right;
}
.address-item {
--paper-item-focused: {
background: transparent;
}
--paper-item-focused-before: {
opacity: 0;
}
}
#sendMoneyWrapper .buttons {
width: auto !important;
}
.address-balance {
font-size: 42px;
font-weight: 100;
.address-item {
--paper-item-focused: {
background: transparent;
}
--paper-item-focused-before: {
opacity: 0;
}
}
.show-transactions {
cursor: pointer;
}
.address-balance {
font-size: 42px;
font-weight: 100;
}
.address-icon {
border-radius: 50%;
border: 5px solid;
padding: 8px;
}
.show-transactions {
cursor: pointer;
}
mwc-textfield {
margin: 0;
}
.address-icon {
border-radius: 50%;
border: 5px solid;
padding: 8px;
}
.selectedBalance {
display: none;
font-size: 14px;
}
.baltxt {
color: var(--black);
}
.selectedBalance .balance {
font-size: 22px;
font-weight: 100;
}
.coinName::before {
content: "";
display: inline-block;
height: 25px;
width: 25px;
position: absolute;
background-repeat: no-repeat;
background-size: cover;
left: 10px;
top: 10px;
}
mwc-textfield {
margin: 0;
}
.qort.coinName:before {
background-image: url('/img/qort.png');
}
.selectedBalance {
display: none;
font-size: 14px;
}
.btc.coinName:before {
background-image: url('/img/btc.png');
}
.selectedBalance .balance {
font-size: 22px;
font-weight: 100;
}
.ltc.coinName:before {
background-image: url('/img/ltc.png');
}
.coinName::before {
content: "";
display: inline-block;
height: 25px;
width: 25px;
position: absolute;
background-repeat: no-repeat;
background-size: cover;
left: 10px;
top: 10px;
}
.doge.coinName:before {
background-image: url('/img/doge.png');
}
.qort.coinName:before {
background-image: url('/img/qort.png');
}
.coinName {
display: inline-block;
height: 25px;
padding-left: 25px;
}
paper-progress {
--paper-progress-active-color: var(--mdc-theme-primary);
}
`
.btc.coinName:before {
background-image: url('/img/btc.png');
}
.ltc.coinName:before {
background-image: url('/img/ltc.png');
}
.doge.coinName:before {
background-image: url('/img/doge.png');
}
.coinName {
display: inline-block;
height: 25px;
padding-left: 25px;
}
paper-progress {
--paper-progress-active-color: var(--mdc-theme-primary);
}
`
}
constructor() {
@ -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 class="layout horizontal center" style=" padding:12px 15px;">
<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>
<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,8 +258,8 @@ class SendMoneyPage extends LitElement {
</mwc-slider>
</div>
<p style="color:red">${this.errorMessage}</p>
<p style="color:green;word-break: break-word;">${this.successMessage}</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-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) {