Dark / Light mode

This commit is contained in:
AlphaX-Projects 2022-03-07 07:35:57 -08:00 committed by GitHub
parent 3faf1e6f79
commit 4c1e4dcba9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 1174 additions and 765 deletions

View File

@ -39,9 +39,9 @@
"@rollup/plugin-commonjs": "^21.0.2", "@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": "^23.0.0", "@vaadin/button": "^23.0.1",
"@vaadin/grid": "^23.0.0", "@vaadin/grid": "^23.0.1",
"@vaadin/icons": "^23.0.0", "@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(--chatmenuhover);
} }
.active { .active {
background: #ebebeb; background: var(--chatmenuactive);
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;
} }
@ -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,12 +140,13 @@ 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() {
return html` return html`
<div id="group-management-page"> <div id="group-management-page">
<div style="min-height:48px; display: flex; padding-bottom: 6px; margin: 2px;"> <div style="min-height: 48px; display: flex; padding-bottom: 6px; margin: 2px;">
<h2 style="margin: 0; flex: 1; padding-top: .1em; display: inline;">Qortal Groups</h2> <h2 style="margin: 0; flex: 1; padding-top: .1em; display: inline;">Qortal Groups</h2>
<mwc-button style="float:right;" @click=${() => this.shadowRoot.querySelector('#createGroupDialog').show()}><mwc-icon>add</mwc-icon>Create Group</mwc-button> <mwc-button style="float:right;" @click=${() => this.shadowRoot.querySelector('#createGroupDialog').show()}><mwc-icon>add</mwc-icon>Create Group</mwc-button>
</div> </div>
@ -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>
@ -182,7 +190,7 @@ class GroupManagement extends LitElement {
<hr> <hr>
</div> </div>
<mwc-textfield style="width:100%;" ?disabled="${this.isLoading}" label="Group Name" id="groupNameInput"></mwc-textfield> <mwc-textfield style="width: 100%;" ?disabled="${this.isLoading}" label="Group Name" id="groupNameInput"></mwc-textfield>
<p style="margin-bottom:0;"> <p style="margin-bottom:0;">
<mwc-textfield style="width:100%;" ?disabled="${this.isLoading}" label="Description" id="groupDescInput"></mwc-textfield> <mwc-textfield style="width:100%;" ?disabled="${this.isLoading}" label="Description" id="groupDescInput"></mwc-textfield>
</p> </p>
@ -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;
} }
@ -64,17 +74,18 @@ class Messaging extends LitElement {
} }
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;
@ -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() {
@ -238,10 +240,10 @@ class MintingInfo extends LitElement {
</div> </div>
<div> <div>
<h3>Introduction</h3><br /> <h3>Introduction</h3><br />
To "activate" your account, an OUTGOING transaction needs to take place. To "activate" your account, an OUTGOING transaction needs to take place.
Name Registration is the most common method. You can ask someone in Q-Chat to send you a small amount of QORT so that you may activate your account, Name Registration is the most common method. You can ask someone in Q-Chat to send you a small amount of QORT so that you may activate your account,
or buy QORT within the Trade Portal then make an OUTGOING transaction of any kind and secure your public key on the blockchain. or buy QORT within the Trade Portal then make an OUTGOING transaction of any kind and secure your public key on the blockchain.
Until you do this, your public key is only known by you, in your UI, and no one else can pull your public key from the chain. Until you do this, your public key is only known by you, in your UI, and no one else can pull your public key from the chain.
</div> </div>
<mwc-button slot="primaryAction" dialogAction="cancel" class="red-button">Close</mwc-button> <mwc-button slot="primaryAction" dialogAction="cancel" class="red-button">Close</mwc-button>
</mwc-dialog> </mwc-dialog>
@ -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,9 +38,14 @@ 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;
} }
@ -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>
@ -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 #eee;
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,12 +35,18 @@ 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 {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
padding: 10px 5px 5px 5px; padding: 10px 5px 5px 5px;
margin: 0px 20px 20px 20px; margin: 0px 20px 20px 20px;
} }
@ -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;
} }
@ -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

@ -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,10 +66,16 @@ class Websites extends LitElement {
padding-bottom: 10px; padding-bottom: 10px;
} }
#pages { mwc-tab-bar {
--mdc-text-transform: none;
--mdc-tab-color-default: var(--black);
--mdc-tab-text-label-color-default: var(--black);
}
#pages {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
padding: 10px 5px 5px 5px; padding: 10px 5px 5px 5px;
margin: 0px 20px 20px 20px; margin: 0px 20px 20px 20px;
} }
@ -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;
} }
@ -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;
} }
@ -167,7 +181,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 {
@ -199,6 +213,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() {
@ -283,7 +298,7 @@ class Websites extends LitElement {
</vaadin-grid> </vaadin-grid>
<div id="pages"></div> <div id="pages"></div>
${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()}
@ -322,7 +337,7 @@ class Websites extends LitElement {
</vaadin-grid-column> </vaadin-grid-column>
</vaadin-grid> </vaadin-grid>
${this.isEmptyArray(this.webResources) ? html` ${this.isEmptyArray(this.webResources) ? html`
You not follow any website <span style="color: var(--black);">You not follow any website</span>
`: ''} `: ''}
</div> </div>
${this.renderRelayModeText()} ${this.renderRelayModeText()}
@ -361,7 +376,7 @@ class Websites extends LitElement {
</vaadin-grid-column> </vaadin-grid-column>
</vaadin-grid> </vaadin-grid>
${this.isEmptyArray(this.blockResources) ? html` ${this.isEmptyArray(this.blockResources) ? html`
You have not blocked any website <span style="color: var(--black);">You have not blocked any website</span>
`: ''} `: ''}
</div> </div>
${this.renderRelayModeText()} ${this.renderRelayModeText()}
@ -373,6 +388,10 @@ class Websites extends LitElement {
firstUpdated() { firstUpdated() {
setInterval(() => {
this.changeTheme();
}, 100)
this.showWebsites() this.showWebsites()
setTimeout(() => { setTimeout(() => {
@ -514,6 +533,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,10 +39,19 @@ 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;
} }
@ -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 }
} }
} }
@ -39,99 +40,111 @@ class SendMoneyPage extends LitElement {
static get styles() { static get styles() {
return css` return css`
* { * {
--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);
--paper-input-container-focus-color: var(--mdc-theme-primary); --paper-input-container-focus-color: var(--mdc-theme-primary);
} }
#sendMoneyWrapper { h2,
} h3,
h4,
h5 {
color: var(--black);
font-weight: 400;
}
#sendMoneyWrapper paper-button { #sendMoneyWrapper {
float: right; }
}
#sendMoneyWrapper .buttons { #sendMoneyWrapper paper-button {
width: auto !important; float: right;
} }
.address-item { #sendMoneyWrapper .buttons {
--paper-item-focused: { width: auto !important;
background: transparent; }
}
--paper-item-focused-before: {
opacity: 0;
}
}
.address-balance { .address-item {
font-size: 42px; --paper-item-focused: {
font-weight: 100; background: transparent;
} }
--paper-item-focused-before: {
opacity: 0;
}
}
.show-transactions { .address-balance {
cursor: pointer; font-size: 42px;
} font-weight: 100;
}
.address-icon { .show-transactions {
border-radius: 50%; cursor: pointer;
border: 5px solid; }
padding: 8px;
}
mwc-textfield { .address-icon {
margin: 0; border-radius: 50%;
} border: 5px solid;
padding: 8px;
}
.selectedBalance { .baltxt {
display: none; color: var(--black);
font-size: 14px; }
}
.selectedBalance .balance { mwc-textfield {
font-size: 22px; margin: 0;
font-weight: 100; }
}
.coinName::before { .selectedBalance {
content: ""; display: none;
display: inline-block; font-size: 14px;
height: 25px; }
width: 25px;
position: absolute;
background-repeat: no-repeat;
background-size: cover;
left: 10px;
top: 10px;
}
.qort.coinName:before { .selectedBalance .balance {
background-image: url('/img/qort.png'); font-size: 22px;
} font-weight: 100;
}
.btc.coinName:before { .coinName::before {
background-image: url('/img/btc.png'); content: "";
} display: inline-block;
height: 25px;
width: 25px;
position: absolute;
background-repeat: no-repeat;
background-size: cover;
left: 10px;
top: 10px;
}
.ltc.coinName:before { .qort.coinName:before {
background-image: url('/img/ltc.png'); background-image: url('/img/qort.png');
} }
.doge.coinName:before { .btc.coinName:before {
background-image: url('/img/doge.png'); background-image: url('/img/btc.png');
} }
.coinName { .ltc.coinName:before {
display: inline-block; background-image: url('/img/ltc.png');
height: 25px; }
padding-left: 25px;
}
paper-progress { .doge.coinName:before {
--paper-progress-active-color: var(--mdc-theme-primary); background-image: url('/img/doge.png');
} }
`
.coinName {
display: inline-block;
height: 25px;
padding-left: 25px;
}
paper-progress {
--paper-progress-active-color: var(--mdc-theme-primary);
}
`
} }
constructor() { constructor() {
@ -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,8 +258,8 @@ 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()
@ -347,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)
} }

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 {
@ -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,7 +271,7 @@ 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 {
@ -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: 1px solid #eee;
} }
.active { .active {
background: #ddd; background: #bbb;
} }
.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: #bbb;
} }
.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 #eee;">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) {