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 # Qortal Project UI
[![License](https://img.shields.io/badge/license-GPL--3.0-blue)](https://opensource.org/licenses/GPL-3.0) [![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 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": { "dependencies": {
"@hapi/hapi": "^20.2.1", "@hapi/hapi": "^20.2.1",
"@hapi/inert": "^6.0.5", "@hapi/inert": "^6.0.5",
"sass": "^1.49.8" "sass": "^1.49.9"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.17.5", "@babel/core": "^7.17.5",
@ -55,17 +55,17 @@
"@polymer/paper-tooltip": "^3.0.1", "@polymer/paper-tooltip": "^3.0.1",
"@rollup/plugin-alias": "^3.1.9", "@rollup/plugin-alias": "^3.1.9",
"@rollup/plugin-babel": "^5.3.1", "@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-node-resolve": "^13.1.3",
"@rollup/plugin-replace": "^4.0.0", "@rollup/plugin-replace": "^4.0.0",
"@vaadin/grid": "^22.0.5", "@vaadin/grid": "^23.0.1",
"@vaadin/password-field": "^22.0.5", "@vaadin/password-field": "^23.0.1",
"asmcrypto.js": "^2.3.2", "asmcrypto.js": "^2.3.2",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"epml": "^0.3.3", "epml": "^0.3.3",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"lit": "^2.2.0", "lit": "^2.2.0",
"postcss": "^8.4.6", "postcss": "^8.4.7",
"pwa-helpers": "^0.9.1", "pwa-helpers": "^0.9.1",
"random-sentence-generator": "^0.0.8", "random-sentence-generator": "^0.0.8",
"redux": "^4.1.2", "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="icon" type="image/png" sizes="16x16" href="/img/favicon/favicon-16x16.png">
<link rel="manifest" href="/img/favicon/manifest.json"> <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="msapplication-TileImage" content="/img/favicon/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="var(--white)">
<style> <style>
html { html {
@ -55,12 +55,13 @@
body { body {
margin: 0; margin: 0;
padding: 0; padding: 0;
background: #eee; background: background: var(--plugback);
overflow: hidden; overflow: hidden;
} }
</style> </style>
<link rel="stylesheet" href="/build/styles.bundle.css"> <link rel="stylesheet" href="/build/styles.bundle.css">
<link rel="stylesheet" href="/font/material-icons.css"> <link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<title>Qortal</title> <title>Qortal</title>

View File

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

View File

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

View File

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

View File

@ -20,7 +20,12 @@ class SecurityView extends connect(store)(LitElement) {
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5); --lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1); --lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%); --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 { .center-box {
position: relative; position: relative;
top: 45%; top: 45%;
@ -28,6 +33,7 @@ class SecurityView extends connect(store)(LitElement) {
transform: translate(-50%, 0%); transform: translate(-50%, 0%);
text-align: center; text-align: center;
} }
.q-button { .q-button {
display: inline-flex; display: inline-flex;
flex-direction: column; flex-direction: column;
@ -61,7 +67,7 @@ class SecurityView extends connect(store)(LitElement) {
</p> </p>
<div style="max-width: 500px; display: flex; justify-content: center; margin: auto;"> <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> <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>
<div style="max-width: 500px; display: flex; justify-content: center; margin: auto;"> <div style="max-width: 500px; display: flex; justify-content: center; margin: auto;">
<div @click=${() => this.downloadBackup()} class="q-button"> Download BackUp File </div> <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; max-width: 100vw;
height: 100%; height: 100%;
max-height: 100vh; max-height: 100vh;
background-color: #fff; background-color: var(--white);
color: #333333; color: var(--black);
line-height: 1.6; line-height: 1.6;
} }
.decline { .decline {
--mdc-theme-primary: var(--mdc-theme-error) --mdc-theme-primary: var(--mdc-theme-error)
} }
paper-dialog.userSettings { paper-dialog.userSettings {
width: 100%; width: 100%;
max-width: 100vw; max-width: 100vw;
height: 100%; height: 100%;
max-height: 100vh; max-height: 100vh;
background-color: #fff; background-color: var(--white);
color: #333333; color: var(--black);
line-height: 1.6; line-height: 1.6;
overflow-y: auto; overflow-y: auto;
} }
.actions { .actions {
display:flex; display:flex;
justify-content: space-between; justify-content: space-between;
padding: 0 4em; padding: 0 4em;
margin: 15px 0 -2px 0; margin: 15px 0 -2px 0;
} }
.close-icon { .close-icon {
font-size: 36px; font-size: 36px;
} }
.close-icon:hover { .close-icon:hover {
cursor: pointer; cursor: pointer;
opacity: .6; opacity: .6;
} }
.buttons { .buttons {
text-align:right; text-align:right;
} }
.container { .container {
max-width: 90vw; max-width: 90vw;
margin-left: auto; margin-left: auto;
@ -68,107 +75,127 @@ class UserSettings extends connect(store)(LitElement) {
margin-top: 20px; margin-top: 20px;
padding: .6em; padding: .6em;
} }
ul { ul {
list-style: none; list-style: none;
padding: 0; padding: 0;
margin-bottom: 0; margin-bottom: 0;
} }
.leftBar { .leftBar {
background-color: #fff; background-color: var(--white);
color: #333333; color: var(--black);
border: 1px solid #a1a1a1; border: 1px solid var(--border);
padding: 20px 0 0 0; padding: 20px 0 0 0;
border-radius: 5px; border-radius: 5px;
} }
.leftBar img { .leftBar img {
margin: 0 auto; margin: 0 auto;
width: 75%; width: 75%;
height: 75%; height: 75%;
text-align: center; text-align: center;
} }
.leftBar .slug { .leftBar .slug {
text-align: center; text-align: center;
margin-top: 20px; margin-top: 20px;
color: #333333; color: var(--black);
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
margin-bottom: 7px; margin-bottom: 7px;
} }
.leftBar ul li { .leftBar ul li {
border-bottom: 1px solid #DDD; border-bottom: 1px solid var(--border);
} }
.leftBar ul li:last-child { .leftBar ul li:last-child {
border-bottom: none; border-bottom: none;
} }
.leftBar ul li a { .leftBar ul li a {
color: #333333; color: var(--black);
font-size: 16px; font-size: 16px;
font-weight: 400; font-weight: 400;
text-decoration: none; text-decoration: none;
padding: .9em; padding: .9em;
display: block; display: block;
} }
.leftBar ul li a i { .leftBar ul li a i {
margin-right: 8px; margin-right: 8px;
font-size: 16px; font-size: 16px;
} }
.leftBar ul li a:hover { .leftBar ul li a:hover {
background-color: #f6f6f6; background-color: var(--menuhover);
color: #515151; color: #515151;
} }
.leftBar ul li:active { .leftBar ul li:active {
border-bottom: none; border-bottom: none;
} }
.leftBar ul li a.active { .leftBar ul li a.active {
color: #515151; color: #515151;
background-color: #eee; background-color: var(--menuactive);
border-left: 2px solid #515151; border-left: 2px solid #515151;
margin-left: -2px; margin-left: -2px;
} }
.mainPage { .mainPage {
background-color: #fff; background-color: var(--white);
color: #333333; color: var(--black);
border: 1px solid #a1a1a1; border: 1px solid var(--border);
padding: 20px 0 10px 0; padding: 20px 0 10px 0;
border-radius: 5px; border-radius: 5px;
font-size: 16px; font-size: 16px;
text-align: center; text-align: center;
min-height: 460px; min-height: 460px;
} }
@media(max-width:700px) { @media(max-width:700px) {
.mainPage { .mainPage {
margin-top: 30px; margin-top: 30px;
} }
} }
@media(min-width:765px) { @media(min-width:765px) {
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
box-sizing: border-box; box-sizing: border-box;
} }
.actions { .actions {
display:flex; display:flex;
justify-content: space-between; justify-content: space-between;
padding: 0 4em; padding: 0 4em;
margin: 15px 0 -25px 0; margin: 15px 0 -25px 0;
} }
.container { .container {
padding: 2em; padding: 2em;
} }
.wrapper { .wrapper {
display: grid; display: grid;
grid-template-columns: 1fr 3fr; grid-template-columns: 1fr 3fr;
grid-gap: 30px; grid-gap: 30px;
} }
.wrapper > .mainPage { .wrapper > .mainPage {
padding: 2em; padding: 2em;
} }
.leftBar { .leftBar {
text-align: left; text-align: left;
max-height: 403px; max-height: 403px;
max-width: 400px; max-width: 400px;
font-size: 16px; font-size: 16px;
} }
.mainPage { .mainPage {
font-size: 16px; font-size: 16px;
} }

View File

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

View File

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

View File

@ -41,7 +41,7 @@ class CopyTextMenu extends connect(store)(LitElement) {
position: absolute; position: absolute;
pointer-events: none; pointer-events: none;
padding: 5px, 0; padding: 5px, 0;
border: 1px solid #B2B2B2; border: 1px solid var(--border);
min-width: 150px; min-width: 150px;
max-width: 300px; max-width: 300px;
background: #F9F9F9; 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 './styles.scss'
import './app-theme.js' import './app-theme.js'
class AppStyles extends LitElement { class AppStyles extends LitElement {
// static get styles () {
// return [
// css`
// html, * {
// color: var(--color, green);
// }
// `
// ]
// }
/* Disable shadow DOM, so that the styles DO bleed */ /* Disable shadow DOM, so that the styles DO bleed */
createRenderRoot () { createRenderRoot () {
@ -23,12 +13,6 @@ class AppStyles extends LitElement {
render () { render () {
return html` return html`
<style> <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/ */ /* 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); --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-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-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); --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); --paper-input-container-focus-color: var(--mdc-theme-secondary);
font-family: "Roboto", sans-serif; font-family: "Roboto", sans-serif;
@ -65,20 +48,15 @@ class AppStyles extends LitElement {
_windowResized () { _windowResized () {
const ua = navigator.userAgent const ua = navigator.userAgent
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i.test(ua) 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 isChrome = /Chrome/i.test(ua)
const isSafari = /Version\/[\d\.]+.*Safari/.test(ua) const isSafari = /Version\/[\d\.]+.*Safari/.test(ua)
if (isMobile && isChrome) { if (isMobile && isChrome) {
this.windowHeight = html`calc(100vh - 56px)` this.windowHeight = html`calc(100vh - 56px)`
// document.body.style.setProperty('--window-height', 'calc(100vh - 56px)')
// console.log('not same')
} else if (isMobile && isSafari) { } else if (isMobile && isSafari) {
this.windowHeight = html`calc(100vh - 72px)` this.windowHeight = html`calc(100vh - 72px)`
} else { } else {
this.windowHeight = html`100vh` 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 { connect } from 'pwa-helpers'
import { store } from '../store.js' import { store } from '../store.js'
class AppTheme extends connect(store)(LitElement) { class AppTheme extends connect(store)(LitElement) {
// static get styles () {
// return [
// css`
// html, * {
// color: var(--color, green);
// }
// `
// ]
// }
static get properties () { static get properties () {
return { 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", "@polymer/paper-spinner": "^3.0.2",
"@rollup/plugin-alias": "^3.1.9", "@rollup/plugin-alias": "^3.1.9",
"@rollup/plugin-babel": "^5.3.1", "@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-node-resolve": "^13.1.3",
"@rollup/plugin-replace": "^4.0.0", "@rollup/plugin-replace": "^4.0.0",
"@vaadin/button": "^22.0.5", "@vaadin/button": "^23.0.1",
"@vaadin/grid": "^22.0.5", "@vaadin/grid": "^23.0.1",
"@vaadin/icons": "^22.0.5", "@vaadin/icons": "^23.0.1",
"epml": "^0.3.3", "epml": "^0.3.3",
"html-escaper": "^3.0.3", "html-escaper": "^3.0.3",
"lit": "^2.2.0", "lit": "^2.2.0",

View File

@ -23,26 +23,34 @@ class ChatHead extends LitElement {
cursor: pointer; cursor: pointer;
width: 100%; width: 100%;
} }
li:hover { li:hover {
background-color: #eee; background-color: var(--menuhover);
} }
.active { .active {
background: #ebebeb; background: var(--menuactive);
border-left: 4px solid #3498db; border-left: 4px solid #3498db;
} }
.img-icon { .img-icon {
float: left; float: left;
font-size:40px; font-size:40px;
color: var(--black);
} }
.about { .about {
margin-top: 8px; margin-top: 8px;
} }
.about { .about {
padding-left: 8px; padding-left: 8px;
} }
.status { .status {
color: #92959e; color: #92959e;
} }
.clearfix:after { .clearfix:after {
visibility: hidden; visibility: hidden;
display: block; 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' : ''}"> <li @click=${() => this.getUrl(this.chatInfo.url)} class="clearfix ${this.activeChatHeadUrl === this.chatInfo.url ? 'active' : ''}">
<mwc-icon class="img-icon">account_circle</mwc-icon> <mwc-icon class="img-icon">account_circle</mwc-icon>
<div class="about"> <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> </div>
</li> </li>
` `

View File

@ -39,11 +39,13 @@ class ChatPage extends LitElement {
html { html {
scroll-behavior: smooth; scroll-behavior: smooth;
} }
.chat-text-area { .chat-text-area {
display: flex; display: flex;
justify-content: center; justify-content: center;
overflow: hidden; overflow: hidden;
} }
.chat-text-area .typing-area { .chat-text-area .typing-area {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -53,12 +55,16 @@ class ChatPage extends LitElement {
box-sizing: border-box; box-sizing: border-box;
padding: 5px; padding: 5px;
margin-bottom: 8px; margin-bottom: 8px;
border: 1px solid rgba(0, 0, 0, 0.3); border: 1px solid var(--black);
border-radius: 10px; border-radius: 10px;
background: #f1f1f1;
color: var(--black);
} }
.chat-text-area .typing-area textarea { .chat-text-area .typing-area textarea {
display: none; display: none;
} }
.chat-text-area .typing-area .chat-editor { .chat-text-area .typing-area .chat-editor {
border-color: transparent; border-color: transparent;
flex: 1; flex: 1;
@ -68,6 +74,7 @@ class ChatPage extends LitElement {
padding: 0; padding: 0;
border: none; border: none;
} }
.chat-text-area .typing-area .emoji-button { .chat-text-area .typing-area .emoji-button {
width: 45px; width: 45px;
height: 40px; height: 40px;
@ -77,7 +84,9 @@ class ChatPage extends LitElement {
background: transparent; background: transparent;
cursor: pointer; cursor: pointer;
max-height: 40px; max-height: 40px;
color: var(--black);
} }
.float-left { .float-left {
float: left; float: left;
} }
@ -88,15 +97,11 @@ class ChatPage extends LitElement {
` `
} }
updated(changedProps) {
}
constructor() { constructor() {
super() super()
this.getOldMessage = this.getOldMessage.bind(this) this.getOldMessage = this.getOldMessage.bind(this)
this._sendMessage = this._sendMessage.bind(this) this._sendMessage = this._sendMessage.bind(this)
this._downObserverhandler = this._downObserverhandler.bind(this) this._downObserverhandler = this._downObserverhandler.bind(this)
this.selectedAddress = {} this.selectedAddress = {}
this.chatId = '' this.chatId = ''
this.myAddress = '' this.myAddress = ''
@ -122,7 +127,7 @@ class ChatPage extends LitElement {
<div class="chat-text-area"> <div class="chat-text-area">
<div class="typing-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> <iframe class="chat-editor" id="_chatEditorDOM" tabindex="-1"></iframe>
<button class="emoji-button" ?disabled=${this.isLoading || this.isLoadingMessages}> <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) { renderChatScroller(initialMessages) {
return html`<chat-scroller .initialMessages=${initialMessages} .emojiPicker=${this.emojiPicker} .escapeHTML=${escape} .getOldMessage=${this.getOldMessage} > </chat-scroller>` 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) this.newMessages = this.newMessages.concat(_newMessages)
} }
} }
/** /**
@ -574,112 +684,6 @@ class ChatPage extends LitElement {
observer.observe(downObserver) 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) { pasteToTextBox(textarea) {
// Return focus to the window // Return focus to the window

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,16 +5,26 @@ const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
class Messaging extends LitElement { class Messaging extends LitElement {
static get properties() { static get properties() {
return {} return {
theme: { type: String, reflect: true }
}
} }
static get styles() { static get styles() {
return css` return css`
* { * {
--mdc-theme-primary: rgb(3, 169, 244); --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 { #page {
background: #fff; background: var(--white);
padding: 12px 24px; padding: 12px 24px;
} }
@ -24,7 +34,7 @@ class Messaging extends LitElement {
} }
h3, h4, h5 { h3, h4, h5 {
color:#333; color: var(--black);
font-weight: 400; font-weight: 400;
} }
@ -57,24 +67,25 @@ class Messaging extends LitElement {
} }
.divCard { .divCard {
border: 1px solid #eee; border: 1px solid var(--border);
padding: 1em; 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); 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; margin-bottom: 1.5rem;
} }
p { p {
color:#333; color: var(--black);
} }
ul, ul li { ul, ul li {
color:#333; color: var(--black);
} }
` `
} }
constructor() { constructor() {
super() super()
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
} }
render() { 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>. 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> 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> <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;">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> <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() { firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
window.addEventListener("contextmenu", (event) => { window.addEventListener("contextmenu", (event) => {
event.preventDefault(); event.preventDefault();
@ -178,11 +181,27 @@ class Messaging extends LitElement {
} }
}) })
}) })
parentEpml.imReady() 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) { _textMenu(event) {
const getSelectedText = () => { const getSelectedText = () => {

View File

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

View File

@ -23,16 +23,22 @@ class Chat extends LitElement {
messages: { type: Array }, messages: { type: Array },
btnDisable: { type: Boolean }, btnDisable: { type: Boolean },
isLoading: { type: Boolean }, isLoading: { type: Boolean },
balance: { type: Number } balance: { type: Number },
theme: { type: String, reflect: true }
} }
} }
static get styles() { static get styles() {
return css` return css`
* { * {
--mdc-theme-primary: rgb(3, 169, 244); --mdc-theme-primary: rgb(3, 169, 244);
--paper-input-container-focus-color: var(--mdc-theme-primary); --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{ paper-spinner-lite{
@ -56,7 +62,7 @@ class Chat extends LitElement {
.container { .container {
margin: 0 auto; margin: 0 auto;
width: 100%; width: 100%;
background: #fff; background: var(--white);
} }
.people-list { .people-list {
@ -76,8 +82,8 @@ class Chat extends LitElement {
border: none; border: none;
display: inline-block; display: inline-block;
padding: 14px; padding: 14px;
color: white; color: var(--white);
background: #6a6c75; background: var(--tradehead);
width: 90%; width: 90%;
font-size: 15px; font-size: 15px;
text-align: center; text-align: center;
@ -100,7 +106,7 @@ class Chat extends LitElement {
width: 80vw; width: 80vw;
height: 100vh; height: 100vh;
float: left; float: left;
background: #fff; background: var(--white);
border-top-right-radius: 5px; border-top-right-radius: 5px;
border-bottom-right-radius: 5px; border-bottom-right-radius: 5px;
color: #434651; color: #434651;
@ -120,8 +126,8 @@ class Chat extends LitElement {
left: 20vw; left: 20vw;
right: 0; right: 0;
z-index: 5; z-index: 5;
background: #6a6c75; background: var(--tradehead);
color: white; color: var(--white);
border-radius: 0 0 8px 8px; border-radius: 0 0 8px 8px;
min-height: 25px; min-height: 25px;
transition: opacity .15s; transition: opacity .15s;
@ -146,7 +152,7 @@ class Chat extends LitElement {
right: 0; right: 0;
bottom: 100%; bottom: 100%;
left: 20vw; left: 20vw;
border-bottom: 2px solid white; border-bottom: 2px solid var(--white);
overflow-y: hidden; overflow-y: hidden;
height: 100vh; height: 100vh;
box-sizing: border-box; box-sizing: border-box;
@ -202,6 +208,7 @@ class Chat extends LitElement {
clear: both; clear: both;
height: 0; height: 0;
} }
.red { .red {
--mdc-theme-primary: red; --mdc-theme-primary: red;
} }
@ -211,7 +218,7 @@ class Chat extends LitElement {
} }
h2, h3, h4, h5 { h2, h3, h4, h5 {
color:#333; color: var(--black);
font-weight: 400; font-weight: 400;
} }
@ -219,16 +226,19 @@ class Chat extends LitElement {
display: hidden !important; display: hidden !important;
visibility: none !important; visibility: none !important;
} }
.details { .details {
display: flex; display: flex;
font-size: 18px; font-size: 18px;
} }
.title { .title {
font-weight:600; font-weight:600;
font-size:12px; font-size:12px;
line-height: 32px; line-height: 32px;
opacity: 0.66; opacity: 0.66;
} }
.input { .input {
width: 100%; width: 100%;
border: none; border: none;
@ -239,6 +249,7 @@ class Chat extends LitElement {
resize: none; resize: none;
background: #eee; background: #eee;
} }
.textarea { .textarea {
width: 100%; width: 100%;
border: none; border: none;
@ -271,17 +282,13 @@ class Chat extends LitElement {
this.messages = [] this.messages = []
this.btnDisable = false this.btnDisable = false
this.isLoading = false this.isLoading = false
this.showNewMesssageBar = this.showNewMesssageBar.bind(this) this.showNewMesssageBar = this.showNewMesssageBar.bind(this)
this.hideNewMesssageBar = this.hideNewMesssageBar.bind(this) this.hideNewMesssageBar = this.hideNewMesssageBar.bind(this)
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
} }
render() { render() {
return html` return html`
<style>
</style>
<div class="container clearfix"> <div class="container clearfix">
<div class="people-list" id="people-list"> <div class="people-list" id="people-list">
<div class="search"> <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() { firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 250)
const stopKeyEventPropagation = (e) => { const stopKeyEventPropagation = (e) => {
e.stopPropagation(); e.stopPropagation();
return false; return false;
@ -455,6 +411,7 @@ class Chat extends LitElement {
} }
let configLoaded = false let configLoaded = false
parentEpml.ready().then(() => { parentEpml.ready().then(() => {
parentEpml.subscribe('selected_address', async selectedAddress => { parentEpml.subscribe('selected_address', async selectedAddress => {
this.selectedAddress = {} this.selectedAddress = {}
@ -485,10 +442,73 @@ class Chat extends LitElement {
} }
}) })
}) })
parentEpml.imReady() 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() { _sendMessage() {
this.isLoading = true this.isLoading = true

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,8 +7,7 @@ import '@material/mwc-icon'
import '@material/mwc-textfield' import '@material/mwc-textfield'
import '@material/mwc-button' import '@material/mwc-button'
import '@material/mwc-dialog' import '@material/mwc-dialog'
import '@vaadin/grid/vaadin-grid.js' import '@vaadin/grid'
import '@vaadin/grid/theme/material/all-imports.js'
const parentEpml = new Epml({ type: "WINDOW", source: window.parent }) const parentEpml = new Epml({ type: "WINDOW", source: window.parent })
@ -31,7 +30,8 @@ class NodeManagement extends LitElement {
removeMintingAccountMessage: { type: String }, removeMintingAccountMessage: { type: String },
tempMintingAccount: { type: Object }, tempMintingAccount: { type: Object },
nodeConfig: { 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-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1); --lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%); --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 { paper-spinner-lite {
@ -54,7 +60,7 @@ class NodeManagement extends LitElement {
} }
#node-management-page { #node-management-page {
background: #fff; background: var(--white);
} }
mwc-textfield { mwc-textfield {
@ -77,7 +83,7 @@ class NodeManagement extends LitElement {
.node-card { .node-card {
padding: 12px 24px; padding: 12px 24px;
background: #fff; background: var(--white);
border-radius: 2px; border-radius: 2px;
box-shadow: 11; box-shadow: 11;
} }
@ -90,10 +96,14 @@ class NodeManagement extends LitElement {
h3, h3,
h4, h4,
h5 { h5 {
color: #333; color: var(--black);
font-weight: 400; font-weight: 400;
} }
.sblack {
color: var(--black);
}
[hidden] { [hidden] {
display: hidden !important; display: hidden !important;
visibility: none !important; visibility: none !important;
@ -127,6 +137,7 @@ class NodeManagement extends LitElement {
}; };
this.nodeConfig = {}; this.nodeConfig = {};
this.nodeDomain = ""; this.nodeDomain = "";
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light';
} }
render() { render() {
@ -134,7 +145,7 @@ class NodeManagement extends LitElement {
<div id="node-management-page"> <div id="node-management-page">
<div class="node-card"> <div class="node-card">
<h2>Node management for: ${this.nodeDomain}</h2> <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 /> <br /><br />
<div id="minting"> <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) 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-column>
</vaadin-grid> </vaadin-grid>
${this.isEmptyArray(this.mintingAccounts) ? html`<span style="color: var(--black);">No minting accounts found for this node</span>` : ""}
${this.isEmptyArray(this.mintingAccounts) ? html` No minting accounts found for this node ` : ""}
</div> </div>
<br /> <br />
@ -267,7 +277,7 @@ class NodeManagement extends LitElement {
}}></vaadin-grid-column> }}></vaadin-grid-column>
</vaadin-grid> </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> </div>
<br /> <br />
</div> </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) { forceSyncPeer(peerAddress, rowIndex) {
parentEpml parentEpml
.request("apiCall", { .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() { getApiKey() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]; const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
let apiKey = myNode.apiKey; let apiKey = myNode.apiKey;

View File

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

View File

@ -29,7 +29,8 @@ class Puzzles extends LitElement {
selectedAddress: { type: Object }, selectedAddress: { type: Object },
selectedPuzzle: { type: Object }, selectedPuzzle: { type: Object },
error: { type: Boolean }, 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-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1); --lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%); --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 { #puzzle-page {
background: #fff; background: var(--white);
padding: 12px 24px; padding: 12px 24px;
} }
@ -54,7 +62,7 @@ class Puzzles extends LitElement {
} }
h2, h3, h4, h5 { h2, h3, h4, h5 {
color:#333; color: var(--black);
font-weight: 400; font-weight: 400;
} }
@ -66,6 +74,13 @@ class Puzzles extends LitElement {
font-family: "Lucida Console", "Courier New", monospace; font-family: "Lucida Console", "Courier New", monospace;
font-size: smaller; 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.selectedPuzzle = {}
this.error = false this.error = false
this.message = '' this.message = ''
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
} }
render() { render() {
@ -154,6 +170,11 @@ class Puzzles extends LitElement {
} }
firstUpdated() { firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
window.addEventListener("contextmenu", (event) => { window.addEventListener("contextmenu", (event) => {
event.preventDefault(); event.preventDefault();
this._textMenu(event) 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) { async guessPuzzle(puzzle) {
this.selectedPuzzle = puzzle this.selectedPuzzle = puzzle
this.shadowRoot.getElementById("puzzleGuess").value = '' this.shadowRoot.getElementById("puzzleGuess").value = ''

View File

@ -19,7 +19,8 @@ class WebBrowser extends LitElement {
service: { type: String }, service: { type: String },
identifier: { type: String }, identifier: { type: String },
followedNames: { type: Array }, followedNames: { type: Array },
blockedNames: { type: Array } blockedNames: { type: Array },
theme: { type: String, reflect: true }
} }
} }
@ -49,7 +50,7 @@ class WebBrowser extends LitElement {
left: 0; left: 0;
right: 0; right: 0;
height: 100px; height: 100px;
background-color: white; background-color: var(--white);
height: 36px; height: 36px;
} }
@ -63,7 +64,7 @@ class WebBrowser extends LitElement {
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
border-top: 1px solid #000000; border-top: 1px solid var(--black);
} }
.iframe-container iframe { .iframe-container iframe {
@ -71,7 +72,7 @@ class WebBrowser extends LitElement {
width: 100%; width: 100%;
height: 100%; height: 100%;
border: none; border: none;
background-color: #ffffff; background-color: var(--white);
} }
input[type=text] { input[type=text] {
@ -80,7 +81,7 @@ class WebBrowser extends LitElement {
border: 0; border: 0;
height: 34px; height: 34px;
font-size: 16px; font-size: 16px;
background-color: #ffffff; background-color: var(--white);
} }
paper-progress { 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() { render() {
return html` 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="layout horizontal center">
<div class="address-bar"> <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.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.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.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> <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> <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.renderBlockUnblockButton()}
${this.renderFollowUnfollowButton()} ${this.renderFollowUnfollowButton()}
</div> </div>
<div class="iframe-container"> <div class="iframe-container">
<iframe id="browser-iframe" src="${this.url}" sandbox="allow-scripts allow-forms allow-downloads"> <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> </iframe>
</div> </div>
</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() { renderFollowUnfollowButton() {
// Only show the follow/unfollow button if we have permission to modify the list on this node // 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)) { if (this.followedNames == null || !Array.isArray(this.followedNames)) {
@ -357,105 +472,6 @@ class WebBrowser extends LitElement {
checkSelectedTextAndShowMenu() 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() { getApiKey() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]; const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
let apiKey = myNode.apiKey; let apiKey = myNode.apiKey;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,7 +24,8 @@ class RewardShare extends LitElement {
removeRewardShareLoading: { type: Boolean }, removeRewardShareLoading: { type: Boolean },
rewardSharePercentage: { type: Number }, rewardSharePercentage: { type: Number },
error: { type: Boolean }, 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-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1); --lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%); --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 { #reward-share-page {
background: #fff; background: var(--white);
padding: 12px 24px; padding: 12px 24px;
} }
.divCard { .divCard {
border: 1px solid #eee; border: 1px solid var(--border);
padding: 1em; 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); 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 { h2, h3, h4, h5 {
color:#333; color: var(--black);
font-weight: 400; font-weight: 400;
} }
@ -75,6 +85,7 @@ class RewardShare extends LitElement {
this.btnDisable = false this.btnDisable = false
this.createRewardShareLoading = false this.createRewardShareLoading = false
this.removeRewardShareLoading = false this.removeRewardShareLoading = false
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
} }
render() { render() {
@ -87,7 +98,7 @@ class RewardShare extends LitElement {
<div class="divCard"> <div class="divCard">
<h3 style="margin: 0; margin-bottom: 1em; text-align: center;">Rewardshares Involving In This Account</h3> <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="mintingAccount"></vaadin-grid-column>
<vaadin-grid-column auto-width path="sharePercent"></vaadin-grid-column> <vaadin-grid-column auto-width path="sharePercent"></vaadin-grid-column>
<vaadin-grid-column auto-width path="recipient"></vaadin-grid-column> <vaadin-grid-column auto-width path="recipient"></vaadin-grid-column>
@ -146,13 +157,18 @@ class RewardShare extends LitElement {
</mwc-button> </mwc-button>
</mwc-dialog> </mwc-dialog>
${this.isEmptyArray(this.rewardShares) ? html` ${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> </div>
` `
} }
firstUpdated() { firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
window.addEventListener("contextmenu", (event) => { window.addEventListener("contextmenu", (event) => {
event.preventDefault(); event.preventDefault();
this._textMenu(event) 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) { renderRemoveRewardShareButton(rewardShareObject) {
if (rewardShareObject.mintingAccount === this.selectedAddress.address) { 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>` 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> <head>
<link rel="stylesheet" href="/font/material-icons.css"> <link rel="stylesheet" href="/font/material-icons.css">
<link rel="stylesheet" href="/font/switch-theme.css">
<style> <style>
html { html {
--scrollbarBG: #a1a1a1; --scrollbarBG: #a1a1a1;
@ -32,7 +33,7 @@
body { body {
margin: 0; margin: 0;
font-family: "Roboto", sans-serif; font-family: "Roboto", sans-serif;
background-color: #fff; background: var(--plugback);
} }
</style> </style>
</head> </head>

View File

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

View File

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

View File

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

View File

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

View File

@ -24,6 +24,7 @@ class MultiWallet extends LitElement {
isTextMenuOpen: { type: Boolean }, isTextMenuOpen: { type: Boolean },
wallets: { type: Map }, wallets: { type: Map },
_selectedWallet: 'qort', _selectedWallet: 'qort',
theme: { type: String, reflect: true },
balanceString: 'Fetching balance ...' balanceString: 'Fetching balance ...'
} }
} }
@ -37,6 +38,10 @@ class MultiWallet extends LitElement {
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5); --lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1); --lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%); --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 { #pages {
@ -56,6 +61,7 @@ class MultiWallet extends LitElement {
font: inherit; font: inherit;
outline: none; outline: none;
cursor: pointer; cursor: pointer;
color: var(--black);
} }
#pages > button:not([disabled]):hover, #pages > button:not([disabled]):hover,
@ -66,7 +72,7 @@ class MultiWallet extends LitElement {
#pages > button[selected] { #pages > button[selected] {
font-weight: bold; font-weight: bold;
color: white; color: var(--white);
background-color: #ccc; background-color: #ccc;
} }
@ -108,7 +114,7 @@ class MultiWallet extends LitElement {
.text-white-primary { .text-white-primary {
color: var(--white-primary); color: var(--white);
} }
.text-white-secondary { .text-white-secondary {
@ -124,6 +130,7 @@ class MultiWallet extends LitElement {
table { table {
border: none; border: none;
} }
table td, table td,
th { th {
white-space: nowrap; white-space: nowrap;
@ -131,39 +138,51 @@ class MultiWallet extends LitElement {
font-size: 14px; font-size: 14px;
padding: 0 12px; padding: 0 12px;
font-family: 'Roboto', sans-serif; font-family: 'Roboto', sans-serif;
color: var(--black);
background: var(--white);
} }
table tr { table tr {
height: 48px; height: 48px;
} }
table tr:hover td { table tr:hover td {
background: #eee; background: #eee;
} }
table tr th { table tr th {
color: #666; color: #666;
font-size: 12px; font-size: 12px;
} }
table tr td { table tr td {
margin: 0; margin: 0;
} }
.white-bg { .white-bg {
height: 100vh; height: 100vh;
background: #fff; background: var(--white);
} }
span { span {
font-size: 18px; font-size: 18px;
word-break: break-all; word-break: break-all;
} }
.title { .title {
font-weight: 600; font-weight: 600;
font-size: 12px; font-size: 12px;
line-height: 32px; line-height: 32px;
opacity: 0.66; opacity: 0.66;
} }
#transactionList { #transactionList {
padding: 0; padding: 0;
} }
#transactionList > * { #transactionList > * {
} }
.color-in { .color-in {
color: #02977e; color: #02977e;
background-color: rgba(0, 201, 167, 0.2); background-color: rgba(0, 201, 167, 0.2);
@ -173,6 +192,7 @@ class MultiWallet extends LitElement {
padding: 0.2rem 0.5rem; padding: 0.2rem 0.5rem;
margin-left: 4px; margin-left: 4px;
} }
.color-out { .color-out {
color: #b47d00; color: #b47d00;
background-color: rgba(219, 154, 4, 0.2); background-color: rgba(219, 154, 4, 0.2);
@ -186,7 +206,7 @@ class MultiWallet extends LitElement {
body { body {
margin: 0; margin: 0;
padding: 0; padding: 0;
background: white; background: var(--white);
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
@ -194,7 +214,7 @@ class MultiWallet extends LitElement {
h2 { h2 {
margin: 0; margin: 0;
font-weight: 400; font-weight: 400;
color: #707584; color: var(--black);
font: 24px/24px 'Open Sans', sans-serif; font: 24px/24px 'Open Sans', sans-serif;
} }
@ -218,7 +238,7 @@ class MultiWallet extends LitElement {
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
border-radius: 8px; border-radius: 8px;
background-color: #fff; background-color: var(--white);
} }
.wallet { .wallet {
@ -226,7 +246,7 @@ class MultiWallet extends LitElement {
height: 100vh; height: 100vh;
border-top-left-radius: inherit; border-top-left-radius: inherit;
border-bottom-left-radius: inherit; border-bottom-left-radius: inherit;
border-right: 1px solid #eee; border-right: 1px solid var(--border);
} }
.transactions-wrapper { .transactions-wrapper {
@ -243,7 +263,7 @@ class MultiWallet extends LitElement {
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 18px; font-size: 18px;
color: var(--mdc-theme-primary, #444750); color: var(--black);
margin: 4px 0 20px; margin: 4px 0 20px;
} }
@ -251,14 +271,14 @@ class MultiWallet extends LitElement {
display: inline-block; display: inline-block;
font-weight: 600; font-weight: 600;
font-size: 32px; font-size: 32px;
color: var(--mdc-theme-primary, #444750); color: var(--black);
} }
#transactions { #transactions {
margin-top: 60px; margin-top: 60px;
margin-left: 20px; margin-left: 20px;
margin-right: 20px; margin-right: 20px;
border-top: 1px solid #e5e5e5; border-top: 1px solid var(--border);
padding-top: 0px; padding-top: 0px;
height: 100%; height: 100%;
} }
@ -275,6 +295,7 @@ class MultiWallet extends LitElement {
margin-bottom: 45px; margin-bottom: 45px;
margin-right: 50px; margin-right: 50px;
} }
.transaction-item::before { .transaction-item::before {
position: absolute; position: absolute;
content: ''; content: '';
@ -324,18 +345,19 @@ class MultiWallet extends LitElement {
.currency-box { .currency-box {
display: flex; display: flex;
background-color: #fff; background-color: var(--white);
text-align: center; text-align: center;
padding: 12px; padding: 12px;
cursor: pointer; cursor: pointer;
transition: 0.1s ease-in-out; transition: 0.1s ease-in-out;
} }
.currency-box:not(:last-child) { .currency-box:not(:last-child) {
border-bottom: 1px solid #eee; border-bottom: var(--border);
} }
.active { .active {
background: #ddd; background: var(--menuactive);
} }
.currency-image { .currency-image {
@ -347,13 +369,16 @@ class MultiWallet extends LitElement {
border-radius: 3px; border-radius: 3px;
filter: grayscale(100%); filter: grayscale(100%);
} }
.currency-box.active .currency-image, .currency-box.active .currency-image,
.currency-box:hover .currency-image { .currency-box:hover .currency-image {
filter: none; filter: none;
} }
.currency-box:hover { .currency-box:hover {
background: #bbb; background: var(--menuhover);
} }
.currency-box.active, .currency-box.active,
.currency-box:hover .currency-text { .currency-box:hover .currency-text {
font-weight: 500; font-weight: 500;
@ -363,7 +388,7 @@ class MultiWallet extends LitElement {
margin: auto 0; margin: auto 0;
margin-left: 8px; margin-left: 8px;
font-size: 20px; font-size: 20px;
color: #777; color: var(--black);
} }
.qort .currency-image { .qort .currency-image {
@ -496,6 +521,8 @@ class MultiWallet extends LitElement {
this.selectWallet = this.selectWallet.bind(this) this.selectWallet = this.selectWallet.bind(this)
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light';
this.wallets = new Map() this.wallets = new Map()
let coinProp = { let coinProp = {
balance: 0, balance: 0,
@ -539,7 +566,7 @@ class MultiWallet extends LitElement {
return html` return html`
<div class="wrapper"> <div class="wrapper">
<div class="wallet"> <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 class="cards">
<div coin="qort" class="currency-box qort active"> <div coin="qort" class="currency-box qort active">
<div class="currency-image"></div> <div class="currency-image"></div>
@ -572,7 +599,7 @@ class MultiWallet extends LitElement {
textToCopy=${this.getSelectedWalletAddress()} textToCopy=${this.getSelectedWalletAddress()}
buttonSize="28px" buttonSize="28px"
iconSize="16px" iconSize="16px"
color="#707584" color="var(--copybutton)"
offsetLeft="4px" offsetLeft="4px"
> >
</button-icon-copy> </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() { getSelectedWalletAddress() {
return this._selectedWallet === 'qort' return this._selectedWallet === 'qort'
? this.wallets.get(this._selectedWallet).wallet.address ? this.wallets.get(this._selectedWallet).wallet.address
: this.wallets.get(this._selectedWallet).wallet.address : this.wallets.get(this._selectedWallet).wallet.address
} }
async getTransactionGrid(coin) { async getTransactionGrid(coin) {
this.transactionsGrid = this.shadowRoot.querySelector(`#${coin}TransactionsGrid`) this.transactionsGrid = this.shadowRoot.querySelector(`#${coin}TransactionsGrid`)
if (coin === 'qort') { if (coin === 'qort') {
@ -675,19 +856,7 @@ class MultiWallet extends LitElement {
} }
return html` return html`
<dom-module id="vaadin-grid-qort-theme" theme-for="vaadin-grid"> <div style="padding-left:12px;" ?hidden="${!this.isEmptyArray(transactions)}"><span style="color: var(--black);">Address has no transactions yet.</span></div>
<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>
<vaadin-grid theme="large" id="${coin}TransactionsGrid" ?hidden="${this.isEmptyArray(this.wallets.get(this._selectedWallet).transactions)}" page-size="25" all-rows-visible> <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 <vaadin-grid-column
auto-width auto-width
@ -734,7 +903,7 @@ class MultiWallet extends LitElement {
renderBTCLikeTransactions(transactions, coin) { renderBTCLikeTransactions(transactions, coin) {
return html` 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 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 auto-width resizable header="Transaction Hash" path="txHash"></vaadin-grid-column>
<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) { showTransactionDetails(myTransaction, allTransactions) {
allTransactions.forEach((transaction) => { allTransactions.forEach((transaction) => {
if (myTransaction.signature === transaction.signature) { if (myTransaction.signature === transaction.signature) {