+
this.openLogout()} title="Logout">
@@ -125,11 +148,8 @@ class AppView extends connect(store)(LitElement) {
`
}
- constructor() {
- super()
- }
-
firstUpdated() {
+ // ...
}
stateChanged(state) {
diff --git a/qortal-ui-core/src/components/language-selector.js b/qortal-ui-core/src/components/language-selector.js
new file mode 100644
index 00000000..f143351c
--- /dev/null
+++ b/qortal-ui-core/src/components/language-selector.js
@@ -0,0 +1,86 @@
+import { LitElement, html, css } from 'lit'
+import { connect } from 'pwa-helpers'
+import { store } from '../store.js'
+import { use, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
+
+registerTranslateConfig({
+ loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
+})
+
+const checkLanguage = localStorage.getItem('qortalLanguage')
+
+if (checkLanguage === null || checkLanguage.length === 0) {
+ localStorage.setItem('qortalLanguage', 'us')
+ use('us')
+} else {
+ use(checkLanguage)
+}
+
+class LanguageSelector extends connect(store)(LitElement) {
+ static get properties() {
+ return {
+ config: { type: Object },
+ theme: { type: String, reflect: true }
+ }
+ }
+
+ static get styles() {
+ return [
+ css`
+ select {
+ width: 175px;
+ height: 34px;
+ padding: 5px 0px 5px 5px;
+ font-size: 16px;
+ border: 1px solid var(--black);
+ border-radius: 3px;
+ color: var(--black);
+ background: var(--white);
+ }
+
+ *:focus {
+ outline: none;
+ }
+
+ select option {
+ line-height: 34px;
+ }
+ `
+ ]
+ }
+
+ constructor() {
+ super()
+ }
+
+ render() {
+ return html`
+
+
+ ${translate("selectmenu.selectlanguage")}
+ US - ${translate("selectmenu.english")}
+ CN - ${translate("selectmenu.chinese")}
+ DE - ${translate("selectmenu.german")}
+ FR - ${translate("selectmenu.french")}
+ PL - ${translate("selectmenu.polish")}
+ SP - ${translate("selectmenu.spanish")}
+
+
+ `
+ }
+
+ firstUpdated() {
+ // ...
+ }
+
+ changeLanguage(event) {
+ use(event.target.value)
+ localStorage.setItem('qortalLanguage', event.target.value)
+ }
+
+ stateChanged(state) {
+ this.config = state.config
+ }
+}
+
+window.customElements.define('language-selector', LanguageSelector)
diff --git a/qortal-ui-core/src/components/login-view/create-account-section.js b/qortal-ui-core/src/components/login-view/create-account-section.js
index e815276f..ad4b40c4 100644
--- a/qortal-ui-core/src/components/login-view/create-account-section.js
+++ b/qortal-ui-core/src/components/login-view/create-account-section.js
@@ -1,6 +1,7 @@
import { LitElement, html, css } from 'lit'
import { connect } from 'pwa-helpers'
import { store } from '../../store.js'
+import { translate, translateUnsafeHTML } from 'lit-translate'
import { createWallet } from '../../../../qortal-ui-crypto/api/createWallet.js'
import FileSaver from 'file-saver'
@@ -47,19 +48,33 @@ class CreateAccountSection extends connect(store)(LitElement) {
_pass: { type: String },
_name: { type: String },
isDownloadedBackup: { type: Boolean },
- nodeConfig: { type: Object }
+ nodeConfig: { type: Object },
+ theme: { type: String, reflect: true }
}
}
static get styles() {
return [
css`
- * {
+ * {
+ --mdc-theme-primary: rgb(3, 169, 244);
+ --mdc-theme-secondary: var(--mdc-theme-primary);
+ --paper-input-container-focus-color: var(--mdc-theme-primary);
+ --mdc-theme-surface: var(--white);
+ --mdc-dialog-content-ink-color: var(--black);
+ --mdc-checkbox-unchecked-color: var(--black);
--lumo-primary-text-color: rgb(0, 167, 245);
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
+ --lumo-base-color: var(--white);
+ --lumo-body-text-color: var(--black);
+ --lumo-secondary-text-color: var(--sectxt);
+ --lumo-contrast-60pct: var(--vdicon);
+ --_lumo-grid-border-color: var(--border);
+ --_lumo-grid-secondary-border-color: var(--border2);
}
+
.red {
--mdc-theme-primary: red;
}
@@ -69,26 +84,27 @@ class CreateAccountSection extends connect(store)(LitElement) {
constructor() {
super()
- this.nextText = 'Next'
- this.backText = 'Back'
+ this.nextText = this.renderNextText()
+ this.backText = this.renderBackText()
this.nextDisabled = false
this._pass = ''
this._name = ''
this.selectedPage = 'info'
- this.nextButtonText = 'Next'
+ this.nextButtonText = this.renderNextText()
this.saveAccount = true
this.showSeedphrase = false
this.isDownloadedBackup = true
this.createAccountLoading = false
- const welcomeMessage = 'Welcome to Qortal'
+ const welcomeMessage = this.renderWelcomeText()
this.welcomeMessage = welcomeMessage
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
this.pages = {
info: {
next: e => {
this.error = false
this.errorMessage = ''
- this.nextButtonText = 'Create'
+ this.nextButtonText = this.renderCreateText()
this.selectPage('password')
this.updateNext()
},
@@ -106,7 +122,7 @@ class CreateAccountSection extends connect(store)(LitElement) {
if (password === '') {
snackbar.add({
- labelText: 'Please enter a Password!',
+ labelText: this.renderEnterPassText(),
dismiss: true
})
return
@@ -114,7 +130,7 @@ class CreateAccountSection extends connect(store)(LitElement) {
if (password != rePassword) {
snackbar.add({
- labelText: 'Passwords not match!',
+ labelText: this.renderNotMatchText(),
dismiss: true
})
return
@@ -122,7 +138,7 @@ class CreateAccountSection extends connect(store)(LitElement) {
if (password.length < 8 && lastPassword !== password) {
snackbar.add({
- labelText: 'Your password is less than 8 characters! This is not recommended. You can continue to ignore this warning.',
+ labelText: this.renderLessText(),
dismiss: true
})
lastPassword = password
@@ -131,7 +147,7 @@ class CreateAccountSection extends connect(store)(LitElement) {
if (this.saveAccount === true && nameInput === '') {
snackbar.add({
- labelText: 'Please enter a Name!',
+ labelText: this.renderEnterNameText(),
dismiss: true
})
return
@@ -179,19 +195,19 @@ class CreateAccountSection extends connect(store)(LitElement) {
next: e => {
if (!this.isDownloadedBackup) {
snackbar.add({
- labelText: 'Your Wallet BackUp file get downloaded!',
+ labelText: this.renderBackupText(),
dismiss: true
})
} else {
if (this.saveAccount) {
- ripple.welcomeMessage = 'Preparing Your Account'
+ ripple.welcomeMessage = this.renderPrepareText()
ripple.open({
x: e.clientX,
y: e.clientY
})
.then(() => {
store.dispatch(doStoreWallet(this._wallet, this._pass, this._name, () => {
- ripple.loadingMessage = 'Loading, Please wait...'
+ ripple.loadingMessage = this.renderLoadingText()
}))
.then(() => {
store.dispatch(doLogin(this._wallet))
@@ -345,21 +361,24 @@ class CreateAccountSection extends connect(store)(LitElement) {
-
Create account
-
- Welcome to Qortal, you will find it to be similar to that of an RPG game,
- you, as a minter on the Qortal network (if you choose to become one) will have the chance to level your account up,
- giving you both more of the QORT block reward and also larger influence over the network in terms of voting on decisions for the platform.
+
${translate("login.createaccount")}
+
+ ${translate("login.createwelcome")}
-
- A ‘ this.shadowRoot.querySelector('#mySeedDialog').show()}>seedphrase Click to view seedphrase ’ will be randomly generated in background. This is used as your private key generator for your blockchain account in Qortal.
+
+ ${translate("login.createa")} ‘ this.shadowRoot.querySelector('#mySeedDialog').show()}>${translate("login.seedphrase")} ${translate("login.click")} ’ ${translate("login.willbe")}
-
- Create your Qortal account by clicking NEXT below.
+
+ ${translate("login.clicknext")}
-
+
+
+
${translate("login.createdseed")}
+
+
+
- this.downloadSeedphrase()}>
+ this.downloadSeedphrase()}>
-
Close
+
${translate("general.close")}
-
Save in browser
-
Your account is now ready to be created. It will be saved in this browser. If you do not want your new account to be saved in your browser, you can uncheck the box below.
- You will still be able to login with your new account(after logging out), using your wallet backup file that you MUST download once you create your account.
+
${translate("login.savein")}
+
${translate("login.ready")}
- perm_identity
-
+ perm_identity
+
- password
-
+ password
+
- password
-
+ password
+
-
- this.shadowRoot.getElementById('saveInBrowserCheckbox').click()}>
+
+ this.shadowRoot.getElementById('saveInBrowserCheckbox').click()}>${translate("login.save")}
{ this.saveAccount = !e.target.checked }} ?checked=${this.saveAccount}>
@@ -418,16 +436,16 @@ class CreateAccountSection extends connect(store)(LitElement) {
-
Save Wallet BackUp File
-
Your account is now created${this.saveAccount ? ' and will be saved in this browser.' : '.'}
-
- This file is the ONLY way to access your account on a system that doesn't have it saved to the app/browser. BE SURE TO BACKUP THIS FILE IN MULTIPLE PLACES. The file is encrypted very securely and decrypted with your local password you created in the previous step. You can save it anywhere securely, but be sure to do that in multiple locations.
-
+
${translate("login.savewallet")}
+
${translate("login.created1")}${this.saveAccount ? this.renderCreateSaveText() : '.'}
+
+ ${translate("login.backup")}
+
-
-
Download Wallet BackUp File
-
this.downloadBackup(this._wallet)} style="dispay: inline;">
- cloud_download Save
+
+ ${translate("login.downloadbackup")}
+ this.downloadBackup(this._wallet)} style="dispay: inline; text-align: center;">
+ cloud_download ${translate("general.save")}
@@ -456,6 +474,62 @@ class CreateAccountSection extends connect(store)(LitElement) {
this._name = ''
}
+ renderBackText() {
+ return html`${translate("general.back")}`
+ }
+
+ renderNextText() {
+ return html`${translate("general.next")}`
+ }
+
+ renderCreateText() {
+ return html`${translate("general.create")}`
+ }
+
+ renderContinueText() {
+ return html`${translate("general.continue")}`
+ }
+
+ renderPrepareText() {
+ return html`${translate("login.prepare")}`
+ }
+
+ renderBackupText() {
+ return html`${translate("login.downloaded")}`
+ }
+
+ renderWelcomeText() {
+ return html`${translate("login.welmessage")}`
+ }
+
+ renderEnterPassText() {
+ return html`${translate("login.pleaseenter")}`
+ }
+
+ renderNotMatchText() {
+ return html`${translate("login.notmatch")}`
+ }
+
+ renderLessText() {
+ return html`${translate("login.lessthen8")}`
+ }
+
+ renderEnterNameText() {
+ return html`${translate("login.entername")}`
+ }
+
+ renderLoadingText() {
+ return html`${translate("login.loading")}`
+ }
+
+ renderCreateAccountText() {
+ return html`${translate("login.createaccount")}`
+ }
+
+ renderCreateSaveText() {
+ return html`${translate("login.created2")}`
+ }
+
_pageChange(newPage, oldPage) {
if (!this.shadowRoot.querySelector('#createAccountPages') || !newPage) {
return
@@ -482,16 +556,16 @@ class CreateAccountSection extends connect(store)(LitElement) {
updateNext() {
if (this.selectedPage === 'info') {
- this.nextText = 'Next'
+ this.nextText = this.renderNextText()
this.nextDisabled = false
} else if (this.selectedPage === 'password') {
this.nextDisabled = false
- this.nextText = 'Create Account'
+ this.nextText = this.renderCreateAccountText()
} else if (this.selectedPage === 'backup') {
this.downloadBackup(this._wallet)
this.nextDisabled = false
this.backHidden = true
- this.nextText = 'Continue'
+ this.nextText = this.renderContinueText()
}
this.updatedProperty()
}
diff --git a/qortal-ui-core/src/components/login-view/login-section.js b/qortal-ui-core/src/components/login-view/login-section.js
index eaae106b..8cd70e87 100644
--- a/qortal-ui-core/src/components/login-view/login-section.js
+++ b/qortal-ui-core/src/components/login-view/login-section.js
@@ -2,6 +2,7 @@ import { LitElement, html, css } from 'lit'
import { connect } from 'pwa-helpers'
import { store } from '../../store.js'
import { checkApiKey } from '../../apiKeyUtils.js'
+import { translate, translateUnsafeHTML } from 'lit-translate'
import '@material/mwc-button'
import '@material/mwc-checkbox'
@@ -43,19 +44,40 @@ class LoginSection extends connect(store)(LitElement) {
saveInBrowser: { type: Boolean },
backedUpWalletJSON: { type: Object },
backedUpSeedLoading: { type: Boolean },
- nodeConfig: { type: Object }
+ nodeConfig: { type: Object },
+ theme: { type: String, reflect: true }
}
}
static get styles() {
return [
css`
- * {
+ * {
+ --mdc-theme-primary: rgb(3, 169, 244);
+ --mdc-theme-secondary: var(--mdc-theme-primary);
+ --paper-input-container-focus-color: var(--mdc-theme-primary);
+ --mdc-theme-surface: var(--white);
+ --mdc-dialog-content-ink-color: var(--black);
+ --mdc-checkbox-unchecked-color: var(--black);
--lumo-primary-text-color: rgb(0, 167, 245);
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
- }
+ --lumo-base-color: var(--white);
+ --lumo-body-text-color: var(--black);
+ --lumo-secondary-text-color: var(--sectxt);
+ --lumo-contrast-60pct: var(--vdicon);
+ --_lumo-grid-border-color: var(--border);
+ --_lumo-grid-secondary-border-color: var(--border2);
+ }
+
+ mwc-formfield {
+ color: var(--black);
+ }
+
+ .red {
+ --mdc-theme-primary: red;
+ }
`
]
}
@@ -63,33 +85,34 @@ class LoginSection extends connect(store)(LitElement) {
constructor() {
super()
this.nextHidden = true
- this.backText = 'Back'
+ this.backText = this.renderBackText()
this.backedUpSeedLoading = false
this.hasStoredWallets = Object.keys(store.getState().user.storedWallets).length > 0
this.selectedPage = this.hasStoredWallets ? 'storedWallet' : 'loginOptions'
this.selectedWallet = {}
this.loginErrorMessage = ''
this.saveInBrowser = false
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
this.loginOptions = [
{
page: 'phrase',
- linkText: 'Seedphrase',
+ linkText: this.renderSeedText(),
icon: 'short_text'
},
{
page: 'storedWallet',
- linkText: 'Saved account',
+ linkText: this.renderSavedText(),
icon: 'save'
},
{
page: 'seed',
- linkText: 'Qora address seed',
+ linkText: this.renderQoraText(),
icon: 'clear_all'
},
{
page: 'backedUpSeed',
- linkText: 'Qortal wallet backup',
+ linkText: this.renderBackupText(),
icon: 'insert_drive_file'
}
]
@@ -121,7 +144,7 @@ class LoginSection extends connect(store)(LitElement) {
border-top: 1px solid #eee;
overflow-y: auto;
box-shadow: 0 0 15px 0px rgb(0 0 0 / 10%);
- background: rgb(253 253 253 / 50%);
+ background: var(--white);
margin: 2vh;
}
@@ -153,13 +176,15 @@ class LoginSection extends connect(store)(LitElement) {
.wallet .walletAddress {
height: 40px !important;
line-height: 40px !important;
+ color: var(--black);
}
.wallet .walletName {
+ color: var(--black);
}
.wallet p span {
- color: #888;
+ color: var(--black);
font-size: 12px;
width: 50px;
display: inline-block;
@@ -184,6 +209,7 @@ class LoginSection extends connect(store)(LitElement) {
.loginIcon {
padding-right: 12px;
margin-top: -2px;
+ color: var(--black);
}
*[hidden] {
@@ -247,7 +273,7 @@ class LoginSection extends connect(store)(LitElement) {
-
How would you like to login?
+
${translate("login.howlogin")}
${this.loginOptions.map(({ page, linkText, icon }) => html`
{ this.selectedPage = page }}>
@@ -255,7 +281,7 @@ class LoginSection extends connect(store)(LitElement) {
${icon}
- ${linkText}
+ ${linkText}
`)}
@@ -263,23 +289,44 @@ class LoginSection extends connect(store)(LitElement) {
-
Your accounts
-
Click your account to login with it
+
${translate("login.youraccounts")}
+
${translate("login.click")}
${(Object.entries(this.wallets || {}).length < 1) ? html`
-
You need to create or save an account before you can log in!
+
${translate("login.needcreate")}
` : ''}
${Object.entries(this.wallets || {}).map(wallet => html`
this.selectWallet(wallet[1])}>
-
Name ${wallet[1].name || "No saved name"}
-
Address ${wallet[1].address0}
+
${translate("login.name")} ${wallet[1].name || "No saved name"}
+
${translate("login.address")} ${wallet[1].address0}
-
this.removeWallet(wallet[1].address0)} icon="clear">
+
this.toDeleteWallet(wallet[1].address0)}" icon="clear">
+
+
+
Qortal UI
+
+
+
+ ${translate("login.areyousure")}
+ this.removeWallet(this.myToDeleteWallet)}"
+ >
+ ${translate("general.yes")}
+
+
+ ${translate("general.no")}
+
+
`)}
@@ -288,32 +335,32 @@ class LoginSection extends connect(store)(LitElement) {
- short_text
-
+ short_text
+
-
-
clear_all
-
+
+ clear_all
+
- account_circle
+ account_circle
- ${this.selectedWallet.address0}
+ ${this.selectedWallet.address0}
${!this.backedUpSeedLoading ? html`
-
Upload your qortal backup
+
${translate("login.upload")}
this.loadBackup(e.detail.result)}">
` : html`
@@ -321,20 +368,20 @@ class LoginSection extends connect(store)(LitElement) {
-
Decrypt backup
+ ${translate("login.decrypt")}
-
+
- perm_identity
-
+ perm_identity
+
- password
- this.keyupEnter(e, e => this.emitNext(e))} autofocus>
+ password
+ this.keyupEnter(e, e => this.emitNext(e))} autofocus>
@@ -342,9 +389,9 @@ class LoginSection extends connect(store)(LitElement) {
${this.loginErrorMessage}
${this.showPasswordCheckboxPages.includes(this.selectedPage) ? html`
-
-
- this.shadowRoot.getElementById('storeCheckbox').click()}>
+
+
+ this.shadowRoot.getElementById('storeCheckbox').click()}>${translate("login.save")}
{ this.saveInBrowser = !e.target.checked }} ?checked="${this.saveInBrowser}">
@@ -370,20 +417,63 @@ class LoginSection extends connect(store)(LitElement) {
})
}
+ renderBackText() {
+ return html`${translate("general.back")}`
+ }
+
+ renderNextText() {
+ return html`${translate("general.next")}`
+ }
+
+ renderLoginText() {
+ return html`${translate("login.login")}`
+ }
+
+ renderSeedText() {
+ return html`${translate("login.seed")}`
+ }
+
+ renderSavedText() {
+ return html`${translate("login.saved")}`
+ }
+
+ renderQoraText() {
+ return html`${translate("login.qora")}`
+ }
+
+ renderBackupText() {
+ return html`${translate("login.backup")}`
+ }
+
+ renderPrepareText() {
+ return html`${translate("login.prepare")}`
+ }
+
+ renderError1Text() {
+ return html`${translate("login.error1")}`
+ }
+
+ renderError2Text() {
+ return html`${translate("login.error2")}`
+ }
+
selectWallet(wallet) {
this.selectedWallet = wallet
this.selectedPage = 'unlockStored'
}
+ toDeleteWallet(deleteAddress) {
+ this.myToDeleteWallet = deleteAddress
+ this.shadowRoot.querySelector('#deleteWalletDialog').show()
+ }
+
removeWallet(walletAddress) {
- if (window.confirm('Are you sure you want to remove this wallet from saved wallets?')) {
- delete store.getState().user.storedWallets[walletAddress]
- this.wallets = store.getState().user.storedWallets
- store.dispatch(
- doRemoveWallet(walletAddress)
- )
- this.cleanup()
- }
+ delete store.getState().user.storedWallets[walletAddress]
+ this.wallets = store.getState().user.storedWallets
+ store.dispatch(
+ doRemoveWallet(walletAddress)
+ )
+ this.cleanup()
}
stateChanged(state) {
@@ -414,7 +504,7 @@ class LoginSection extends connect(store)(LitElement) {
try {
pf = JSON.parse(file)
} catch (e) {
- this.loginErrorMessage = 'Backup must be valid JSON'
+ this.loginErrorMessage = this.renderError1Text()
}
try {
@@ -460,7 +550,7 @@ class LoginSection extends connect(store)(LitElement) {
].includes(selectedPage)
) || (['unlockBackedUpSeed', 'unlockStored'].includes(selectedPage))
- if (willBeShown)//if the password will be displayed lt's give it focus
+ if (willBeShown)
this.shadowRoot.getElementById('password').focus()
return willBeShown
@@ -522,11 +612,11 @@ class LoginSection extends connect(store)(LitElement) {
type = type === 'unlockBackedUpSeed' ? 'backedUpSeed' : type
if (!this.loginOptionIsSelected(type)) {
- throw new Error('Login option not selected page')
+ throw new Error(this.renderError2Text())
}
// First decrypt...
- this.loadingRipple.welcomeMessage = 'Preparing Your Account'
+ this.loadingRipple.welcomeMessage = this.renderPrepareText()
this.loadingRipple.open({
x: e.clientX,
y: e.clientY
@@ -585,12 +675,12 @@ class LoginSection extends connect(store)(LitElement) {
updateNext() {
if (['phrase', 'seed', 'unlockStored', 'unlockBackedUpSeed'].includes(this.selectedPage)) {
- this.nextText = 'Login'
+ this.nextText = this.renderLoginText()
this.nextHidden = false
// Should enable/disable the next button based on whether or not password are inputted
} else if (['storedWallet', 'loginOptions', 'backedUpSeed'].includes(this.selectedPage)) {
this.nextHidden = true
- this.nextText = 'Next'
+ this.nextText = this.renderNextText()
}
this.updatedProperty()
@@ -618,6 +708,7 @@ class LoginSection extends connect(store)(LitElement) {
this.shadowRoot.querySelector('#password').value = ''
this.hasStoredWallets = Object.keys(store.getState().user.storedWallets).length > 0
this.selectedPage = this.hasStoredWallets ? 'storedWallet' : 'loginOptions'
+ this.shadowRoot.querySelector('#deleteWalletDialog').close()
}
}
diff --git a/qortal-ui-core/src/components/login-view/login-view.js b/qortal-ui-core/src/components/login-view/login-view.js
index 489880e7..5b124303 100644
--- a/qortal-ui-core/src/components/login-view/login-view.js
+++ b/qortal-ui-core/src/components/login-view/login-view.js
@@ -27,20 +27,18 @@ class LoginView extends connect(store)(LitElement) {
rippleIsOpen: { type: Boolean },
config: { type: Object },
rippleLoadingMessage: { type: String },
- selectedPageElement: {}
+ selectedPageElement: {},
+ theme: { type: String, reflect: true }
}
}
static get styles() {
return [
- css`
-
- `
+ css``
]
}
getPreSelectedPage() {
-
return 'welcome'
}
@@ -55,6 +53,7 @@ class LoginView extends connect(store)(LitElement) {
login: 2
}
this.rippleLoadingMessage = 'Getting information'
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
firstUpdated() {
@@ -107,7 +106,7 @@ class LoginView extends connect(store)(LitElement) {
}
.login-page {
- background: url("/img/qortal_background_light_.jpg");
+ background: var(--background);
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
diff --git a/qortal-ui-core/src/components/login-view/welcome-page.js b/qortal-ui-core/src/components/login-view/welcome-page.js
index 29c691c3..905c5777 100644
--- a/qortal-ui-core/src/components/login-view/welcome-page.js
+++ b/qortal-ui-core/src/components/login-view/welcome-page.js
@@ -1,4 +1,5 @@
import { LitElement, html, css } from 'lit'
+import { translate, translateUnsafeHTML } from 'lit-translate'
import '@material/mwc-button'
@@ -11,19 +12,27 @@ class WelcomePage extends LitElement {
backHidden: { type: Boolean, notify: true },
backDisabled: { type: Boolean, notify: true },
backText: { type: String, notify: true },
- hideNav: { type: Boolean, notify: true }
+ hideNav: { type: Boolean, notify: true },
+ theme: { type: String, reflect: true }
}
}
static get styles() {
return [
css`
+ * {
+ --mdc-theme-primary: rgb(3, 169, 244);
+ --mdc-theme-secondary: var(--mdc-theme-primary);
+ --mdc-button-outline-color: #03a9f4;
+ }
+
mwc-button {
margin: 6px;
width: 90%;
max-width:90vw;
margin: 4px;
}
+
.welcome-page {
padding: 12px 0;
}
@@ -37,6 +46,7 @@ class WelcomePage extends LitElement {
this.nextText = ''
const welcomeMessage = 'Welcome to Qortal';
this.welcomeMessage = welcomeMessage
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
firstUpdate() {
@@ -56,8 +66,8 @@ class WelcomePage extends LitElement {
-
this.navigate('login')} outlined style="border-top:0; border-bottom:0;">Login
-
this.navigate('create-account')} outlined style="border-top:0; border-bottom:0;">Create account
+
this.navigate('login')} outlined style="border-top:0; border-bottom:0;">${translate("login.login")}
+
this.navigate('create-account')} outlined style="border-top:0; border-bottom:0;">${translate("login.createaccount")}
`
}
diff --git a/qortal-ui-core/src/components/logout-view/logout-view.js b/qortal-ui-core/src/components/logout-view/logout-view.js
index a8f8a636..044b3f74 100644
--- a/qortal-ui-core/src/components/logout-view/logout-view.js
+++ b/qortal-ui-core/src/components/logout-view/logout-view.js
@@ -1,15 +1,16 @@
import { LitElement, html, css } from 'lit'
import { connect } from 'pwa-helpers'
import { store } from '../../store.js'
+import { doLogout } from '../../redux/app/app-actions.js'
+import { translate, translateUnsafeHTML } from 'lit-translate'
import '@polymer/paper-dialog/paper-dialog.js'
import '@material/mwc-button'
-import { doLogout } from '../../redux/app/app-actions.js'
-
class LogoutView extends connect(store)(LitElement) {
static get properties() {
return {
+ theme: { type: String, reflect: true }
}
}
@@ -34,6 +35,7 @@ class LogoutView extends connect(store)(LitElement) {
constructor() {
super()
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
@@ -44,11 +46,11 @@ class LogoutView extends connect(store)(LitElement) {
-
Are you sure you want to logout?
+ ${translate("logout.confirmlogout")}
- this.decline(e)} dialog-dismiss>NO
- this.confirm(e)} dialog-confirm autofocus>YES
+ this.decline(e)} dialog-dismiss>${translate("general.no")}
+ this.confirm(e)} dialog-confirm autofocus>${translate("general.yes")}
`
diff --git a/qortal-ui-core/src/components/settings-view/account-view.js b/qortal-ui-core/src/components/settings-view/account-view.js
index a78bd6af..6861e47a 100644
--- a/qortal-ui-core/src/components/settings-view/account-view.js
+++ b/qortal-ui-core/src/components/settings-view/account-view.js
@@ -1,11 +1,13 @@
import { LitElement, html, css } from 'lit';
import { connect } from 'pwa-helpers';
import { store } from '../../store.js';
+import { translate, translateUnsafeHTML } from 'lit-translate'
class AccountView extends connect(store)(LitElement) {
static get properties() {
return {
- accountInfo: { type: Object }
+ accountInfo: { type: Object },
+ theme: { type: String, reflect: true }
}
}
@@ -62,7 +64,8 @@ class AccountView extends connect(store)(LitElement) {
constructor() {
super()
- this.accountInfo = { names: [], addressInfo: {} };
+ this.accountInfo = { names: [], addressInfo: {} }
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
@@ -74,10 +77,10 @@ class AccountView extends connect(store)(LitElement) {
${this.accountInfo.names.length !== 0 ? this.accountInfo.names[0].name : 'No Registered Name'}
- Address:
+ ${translate("settings.address")}:
${store.getState().app.selectedAddress.address}
- Public Key:
+ ${translate("settings.publickey")}:
${store.getState().app.selectedAddress.base58PublicKey}
diff --git a/qortal-ui-core/src/components/settings-view/notifications-view.js b/qortal-ui-core/src/components/settings-view/notifications-view.js
index f59b98e7..b09ec6ee 100644
--- a/qortal-ui-core/src/components/settings-view/notifications-view.js
+++ b/qortal-ui-core/src/components/settings-view/notifications-view.js
@@ -1,8 +1,8 @@
import { LitElement, html, css } from 'lit'
import { connect } from 'pwa-helpers'
import { store } from '../../store.js'
-
import { doSetQChatNotificationConfig } from '../../redux/user/user-actions.js'
+import { translate, translateUnsafeHTML } from 'lit-translate'
import '@material/mwc-checkbox'
@@ -12,7 +12,8 @@ class NotificationsView extends connect(store)(LitElement) {
return {
notificationConfig: { type: Object },
q_chatConfig: { type: Object },
- blockConfig: { type: Object }
+ blockConfig: { type: Object },
+ theme: { type: String, reflect: true }
}
}
@@ -21,6 +22,7 @@ class NotificationsView extends connect(store)(LitElement) {
this.notificationConfig = {}
this.q_chatConfig = {}
this.blockConfig = {}
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
static get styles() {
@@ -29,6 +31,7 @@ class NotificationsView extends connect(store)(LitElement) {
position: relative;
text-align: center;
}
+
.notification-box {
display: block;
position: relative;
@@ -37,6 +40,7 @@ class NotificationsView extends connect(store)(LitElement) {
transform: translate(-50%, 0%);
text-align: center;
}
+
@media(min-width: 1150px) {
.notification-box {
display: grid;
@@ -44,6 +48,7 @@ class NotificationsView extends connect(store)(LitElement) {
grid-gap: 30px;
}
}
+
.content-box {
border: 1px solid #a1a1a1;
padding: 10px 25px;
@@ -53,15 +58,19 @@ class NotificationsView extends connect(store)(LitElement) {
min-height: 150px;
margin: 20px 0;
}
+
h4 {
margin-bottom: 0;
}
+
mwc-checkbox::shadow .mdc-checkbox::after, mwc-checkbox::shadow .mdc-checkbox::before {
background-color:var(--mdc-theme-primary)
}
+
label:hover {
cursor: pointer;
}
+
.title {
font-weight: 600;
font-size: 15px;
@@ -82,14 +91,14 @@ class NotificationsView extends connect(store)(LitElement) {
-
Q-Chat Notifications
+
Q-Chat ${translate("settings.notifications")}
this.setQChatNotificationConfig({ type: 'PLAY_SOUND', value: e.target.checked })} ?checked=${this.q_chatConfig.playSound}>
this.shadowRoot.getElementById('qChatPlaySound').click()}
- >Play Sound
+ >${translate("settings.playsound")}
@@ -97,20 +106,20 @@ class NotificationsView extends connect(store)(LitElement) {
this.shadowRoot.getElementById('qChatShowNotification').click()}
- >Show Notifications
+ >${translate("settings.shownotifications")}
-
Block Notifications ("Coming Soon...")
+
${translate("settings.block")}
- Play Sound
+ ${translate("settings.playsound")}
- Show Notifications
+ ${translate("settings.shownotifications")}
diff --git a/qortal-ui-core/src/components/settings-view/security-view.js b/qortal-ui-core/src/components/settings-view/security-view.js
index 187a05ce..890fc227 100644
--- a/qortal-ui-core/src/components/settings-view/security-view.js
+++ b/qortal-ui-core/src/components/settings-view/security-view.js
@@ -1,6 +1,7 @@
import { LitElement, html, css } from 'lit'
import { connect } from 'pwa-helpers'
import { store } from '../../store.js'
+import { translate, translateUnsafeHTML } from 'lit-translate'
import '@material/mwc-textfield'
import '@material/mwc-icon'
@@ -10,6 +11,7 @@ import FileSaver from 'file-saver'
class SecurityView extends connect(store)(LitElement) {
static get properties() {
return {
+ theme: { type: String, reflect: true }
}
}
@@ -58,19 +60,24 @@ class SecurityView extends connect(store)(LitElement) {
`
}
+ constructor() {
+ super()
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
+ }
+
render() {
return html`
- Please choose a password to encrypt your backup with (this can be the same as the one you logged in with, or different)
+ ${translate("settings.choose")}
password
-
+
-
this.downloadBackup()} class="q-button"> Download BackUp File
+
this.downloadBackup()} class="q-button"> ${translate("settings.download")}
diff --git a/qortal-ui-core/src/components/settings-view/user-settings.js b/qortal-ui-core/src/components/settings-view/user-settings.js
index 0170fdcd..7665c9ba 100644
--- a/qortal-ui-core/src/components/settings-view/user-settings.js
+++ b/qortal-ui-core/src/components/settings-view/user-settings.js
@@ -1,6 +1,7 @@
import { LitElement, html, css } from 'lit'
import { connect } from 'pwa-helpers'
import { store } from '../../store.js'
+import { translate, translateUnsafeHTML } from 'lit-translate'
import '@polymer/paper-dialog/paper-dialog.js'
import '@material/mwc-button'
@@ -16,7 +17,8 @@ class UserSettings extends connect(store)(LitElement) {
return {
loggedIn: { type: Boolean },
pages: { type: Array },
- selectedView: { type: Object }
+ selectedView: { type: Object },
+ theme: { type: String, reflect: true }
}
}
@@ -206,6 +208,7 @@ class UserSettings extends connect(store)(LitElement) {
constructor() {
super()
this.selectedView = { id: 'info', name: 'General Account Info' }
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
render() {
@@ -218,15 +221,15 @@ class UserSettings extends connect(store)(LitElement) {
-
Qortal UI Settings
+
Qortal UI ${translate("settings.settings")}
-
${ this.selectedView.name}
+ ${this.renderHeaderViews()}
${html`${this.renderSettingViews(this.selectedView)}`}
@@ -250,6 +253,16 @@ class UserSettings extends connect(store)(LitElement) {
}
}
+ renderHeaderViews() {
+ if (this.selectedView.id === 'info') {
+ return html`${translate("settings.generalinfo")}`;
+ } else if (this.selectedView.id === 'security') {
+ return html`${translate("settings.accountsecurity")}`;
+ } else if (this.selectedView.id === 'notification') {
+ return html`UI ${translate("settings.notifications")}`;
+ }
+ }
+
setSettingsView(pageId) {
if (pageId === 'info') {
return this.selectedView = { id: 'info', name: 'General Account Info' }
diff --git a/qortal-ui-core/src/components/sidenav-menu.js b/qortal-ui-core/src/components/sidenav-menu.js
index 8c805454..c730c05d 100644
--- a/qortal-ui-core/src/components/sidenav-menu.js
+++ b/qortal-ui-core/src/components/sidenav-menu.js
@@ -1,6 +1,7 @@
import { LitElement, html, css } from 'lit'
import { connect } from 'pwa-helpers'
import { store } from '../store.js'
+import { translate, translateUnsafeHTML } from 'lit-translate'
import '@material/mwc-icon'
import '@polymer/paper-ripple'
@@ -14,8 +15,10 @@ class SidenavMenu extends connect(store)(LitElement) {
static get properties() {
return {
config: { type: Object },
- urls: { type: Object }
+ urls: { type: Object },
+ theme: { type: String, reflect: true }
}
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
}
static get styles() {
@@ -54,34 +57,34 @@ class SidenavMenu extends connect(store)(LitElement) {
return html`
diff --git a/qortal-ui-core/src/custom-elements/frag-file-input.js b/qortal-ui-core/src/custom-elements/frag-file-input.js
index d3e2d667..e35c4dc0 100644
--- a/qortal-ui-core/src/custom-elements/frag-file-input.js
+++ b/qortal-ui-core/src/custom-elements/frag-file-input.js
@@ -3,15 +3,13 @@ import { LitElement, html, css } from 'lit'
import '@material/mwc-button'
import '@material/mwc-icon'
+import { translate, translateUnsafeHTML } from 'lit-translate'
+
class FragFileInput extends LitElement {
static get properties () {
return {
- accept: {
- type: String
- },
- readAs: {
- type: String
- }
+ accept: { type: String },
+ readAs: { type: String }
}
}
@@ -22,18 +20,23 @@ class FragFileInput extends LitElement {
font-family: "Roboto", sans-serif;
padding: 20px;
}
+
#trigger:hover {
cursor: pointer;
}
+
#drop-area.highlight {
border-color: var(--mdc-theme-primary, #000);
}
+
p {
margin-top: 0;
}
+
form {
margin-bottom: 10px;
}
+
#fileInput {
display: none;
}
@@ -47,30 +50,21 @@ class FragFileInput extends LitElement {
render () {
return html`
-
-
-
-
+
this.shadowRoot.getElementById('fileInput').click()} style="dispay:inline;">
- cloud_upload Select file
-
- Drag and drop backup here
+ cloud_upload ${translate("fragfile.selectfile")}
+
+ ${translate("fragfile.dragfile")}
-
-
-
this.readFile(e.target.files[0])}">
`
}
readFile (file) {
const fr = new FileReader()
-
fr.onload = () => {
this.dispatchEvent(new CustomEvent('file-read-success', {
detail: { result: fr.result },
@@ -78,7 +72,6 @@ class FragFileInput extends LitElement {
composed: true
}))
}
-
fr['readAs' + this.readAs](file)
}
diff --git a/qortal-ui-core/src/functional-components/confirm-transaction-dialog.js b/qortal-ui-core/src/functional-components/confirm-transaction-dialog.js
index 0622f60b..ea519302 100644
--- a/qortal-ui-core/src/functional-components/confirm-transaction-dialog.js
+++ b/qortal-ui-core/src/functional-components/confirm-transaction-dialog.js
@@ -10,7 +10,8 @@ import '@material/mwc-button'
class ConfirmTransactionDialog extends connect(store)(LitElement) {
static get properties() {
return {
- txInfo: { type: Object }
+ txInfo: { type: Object },
+ theme: { type: String, reflect: true }
}
}
@@ -53,6 +54,7 @@ class ConfirmTransactionDialog extends connect(store)(LitElement) {
}
this.txInfo = html``
listenForRequest(args => this.requestTransaction(args))
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light';
}
render() {
diff --git a/qortal-ui-core/src/functional-components/mykey-page.js b/qortal-ui-core/src/functional-components/mykey-page.js
index 1699a6a4..4c422891 100644
--- a/qortal-ui-core/src/functional-components/mykey-page.js
+++ b/qortal-ui-core/src/functional-components/mykey-page.js
@@ -16,7 +16,8 @@ let mykeyDialog
class MykeyPage extends connect(store)(LitElement) {
static get properties() {
return {
- nodeConfig: { type: Object }
+ nodeConfig: { type: Object },
+ theme: { type: String, reflect: true }
}
}
@@ -31,6 +32,7 @@ class MykeyPage extends connect(store)(LitElement) {
constructor() {
super()
this.nodeConfig = {}
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light';
}
render() {
diff --git a/qortal-ui-core/src/functional-components/settings-page.js b/qortal-ui-core/src/functional-components/settings-page.js
index 81faebda..83520f5d 100644
--- a/qortal-ui-core/src/functional-components/settings-page.js
+++ b/qortal-ui-core/src/functional-components/settings-page.js
@@ -1,31 +1,50 @@
import { LitElement, html, css } from 'lit'
import { connect } from 'pwa-helpers'
import { store } from '../store.js'
-
import { doAddNode, doSetNode } from '../redux/app/app-actions.js'
+import snackbar from './snackbar.js'
+import { translate, translateUnsafeHTML } from 'lit-translate'
+import '../components/language-selector.js'
import '@material/mwc-dialog'
import '@material/mwc-button'
import '@material/mwc-select'
import '@material/mwc-textfield'
import '@material/mwc-icon'
-
import '@material/mwc-list/mwc-list-item.js'
-import snackbar from './snackbar.js'
-
let settingsDialog
class SettingsPage extends connect(store)(LitElement) {
static get properties() {
return {
lastSelected: { type: Number },
- nodeConfig: { type: Object }
+ nodeConfig: { type: Object },
+ theme: { type: String, reflect: true }
}
}
static get styles() {
return css`
+ * {
+ --mdc-theme-primary: rgb(3, 169, 244);
+ --mdc-theme-secondary: var(--mdc-theme-primary);
+ --mdc-dialog-content-ink-color: var(--black);
+ --mdc-theme-surface: var(--white);
+ --mdc-theme-text-primary-on-background: var(--black);
+ }
+
+ #main {
+ width: 210px;
+ display: flex;
+ align-items: center;
+ }
+
+ .globe {
+ color: var(--black);
+ --mdc-icon-size: 36px;
+ }
+
.red {
--mdc-theme-primary: red;
}
@@ -35,57 +54,79 @@ class SettingsPage extends connect(store)(LitElement) {
constructor() {
super()
this.nodeConfig = {}
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light';
}
render() {
return html`
-
-
-
-
this.nodeSelected(e)}" style="min-width: 130px; max-width:100%; width:100%;">
+
+
+
${translate("settings.settings")}
+
+
+
+
+
this.nodeSelected(e)}" style="min-width: 130px; max-width:100%; width:100%;">
${this.nodeConfig.knownNodes.map((n, index) => html`
${n.protocol + '://' + n.domain + ':' + n.port}
`)}
-
-
Select a node from the default list of nodes above or add a custom node to the list above by clicking on the button below
-
-
this.shadowRoot.querySelector('#addNodeDialog').show()}">add Add Custom Node
+
${translate("settings.nodehint")}
+
+ this.shadowRoot.querySelector('#addNodeDialog').show()}">add ${translate("settings.addcustomnode")}
+
+
+
- Close
+ ${translate("general.close")}
-
-
+
+
+
${translate("settings.addcustomnode")}
+
+
+
+
http
https
-
-
+
+
- Close
+ ${translate("general.close")}
- Add And Save
+ ${translate("settings.addandsave")}
`
}
+ firstUpdated() {
+ // ...
+ }
+
stateChanged(state) {
this.config = state.config
this.nodeConfig = state.app.nodeConfig
diff --git a/qortal-ui-core/src/functional-components/side-menu-item-style.js b/qortal-ui-core/src/functional-components/side-menu-item-style.js
index aec5bf0b..a90c2d6e 100644
--- a/qortal-ui-core/src/functional-components/side-menu-item-style.js
+++ b/qortal-ui-core/src/functional-components/side-menu-item-style.js
@@ -3,12 +3,12 @@ import { css } from 'lit'
export const sideMenuItemStyle = css`
:host {
--font-family: "Roboto", sans-serif;
- --item-font-size: 1rem;
- --sub-item-font-size: 0.85rem;
- --item-padding: 1rem;
- --item-content-padding: 1rem;
- --icon-height: 1.25rem;
- --icon-width: 1.25rem;
+ --item-font-size: 0.9375rem;
+ --sub-item-font-size: 0.75rem;
+ --item-padding: 0.875rem;
+ --item-content-padding: 0.875rem;
+ --icon-height: 1.125rem;
+ --icon-width: 1.125rem;
--item-border-radius: 5px;
--item-selected-color: #dddddd;
--item-selected-color-text: #333333;
diff --git a/qortal-ui-core/src/redux/app/version.js b/qortal-ui-core/src/redux/app/version.js
index ab705d61..dbe4ce76 100644
--- a/qortal-ui-core/src/redux/app/version.js
+++ b/qortal-ui-core/src/redux/app/version.js
@@ -1 +1 @@
-export const UI_VERSION = "1.7.4";
+export const UI_VERSION = "1.8.2";