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

Merge pull request #47 from Traxo7/master

Adds qr-login settings view
This commit is contained in:
AlphaX-Projects 2022-07-18 12:07:04 +02:00 committed by GitHub
commit 6e0801d54d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 157 additions and 0 deletions

View File

@ -109,6 +109,10 @@ const elementComponents = {
file: 'components/settings-view/security-view.js',
className: 'SecurityView'
},
'qr-login-view': {
file: 'components/settings-view/qr-login-view.js',
className: 'QRLoginView'
},
'notifications-view': {
file: 'components/settings-view/notifications-view.js',
className: 'NotificationsView'

View File

@ -93,6 +93,11 @@
"settings": "Settings",
"account": "Account",
"security": "Security",
"qr_login_menu_item": "QR Login",
"qr_login_description_1": "Scan this code to unlock your wallet on other device using the same password which you logged in with.",
"qr_login_description_2": "Choose a password which you will use to unlock your wallet on other device after scanning the QR code.",
"qr_login_button_1": "Show login QR code",
"qr_login_button_2": "Generate login QR code",
"notifications": "Notifications",
"accountsecurity": "Account Security",
"password": "Password",

View File

@ -0,0 +1,140 @@
import { css, html, LitElement } from 'lit'
import { connect } from 'pwa-helpers'
import { store } from '../../store.js'
import { translate } from 'lit-translate'
import '@material/mwc-textfield'
import '@material/mwc-icon'
import '@vaadin/password-field/vaadin-password-field.js'
import '../../../../qortal-ui-plugins/plugins/core/components/QortalQrcodeGenerator.js'
class QRLoginView extends connect(store)(LitElement) {
static get properties() {
return {
theme: { type: String, reflect: true },
savedWalletDataJson: { type: String },
translateDescriptionKey: { type: String }, // Description text
translateButtonKey: { type: String }, // Button text
}
}
static get styles() {
return css`
* {
--lumo-primary-text-color: rgb(0, 167, 245);
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--lumo-secondary-text-color: var(--sectxt);
--lumo-contrast-60pct: var(--vdicon);
}
.center-box {
position: relative;
top: 45%;
left: 50%;
transform: translate(-50%, 0%);
text-align: center;
}
.q-button {
display: inline-flex;
flex-direction: column;
justify-content: center;
align-content: center;
border: none;
border-radius: 20px;
padding-left: 25px;
padding-right: 25px;
color: white;
background: #03a9f4;
width: 50%;
font-size: 17px;
cursor: pointer;
height: 50px;
margin-top: 1rem;
text-transform: uppercase;
text-decoration: none;
transition: all .2s;
position: relative;
}
.q-button.outlined {
background: unset;
border: 1px solid #03a9f4;
}
:host([theme="light"]) .q-button.outlined {
color: #03a9f4;
}
#qr-toggle-button {
margin-left: 12px;
}
#login-qr-code {
margin: auto;
}
`
}
constructor() {
super()
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
this.translateDescriptionKey = 'settings.qr_login_description_' + (this.isWalletStored() ? '1' : '2')
this.translateButtonKey = 'settings.qr_login_button_' + (this.isWalletStored() ? '1' : '2')
}
render() {
return html`
<div style="position: relative;" >
<div class="center-box">
<p>
${translate(this.translateDescriptionKey)}
</p>
<div style="max-width: 500px; justify-content: center; margin: auto; display: ${this.isWalletStored() ? 'none' : 'flex' }">
<mwc-icon style="padding: 10px; padding-left:0; padding-top: 42px;">password</mwc-icon>
<vaadin-password-field id="newWalletPassword" style="width: 100%; color: var(--black);" label="${translate("settings.password")}" autofocus></vaadin-password-field>
</div>
<div style="max-width: 600px; display: flex; justify-content: center; margin: auto;">
<div id="qr-toggle-button" @click=${() => this.showQRCode()} class="q-button outlined"> ${translate(this.translateButtonKey)} </div>
</div>
<div id="login-qr-code" style="display: none;">
<qortal-qrcode-generator id="login-qr-code" data="${this.savedWalletDataJson}" mode="octet" format="html" auto></qortal-qrcode-generator>
</div>
</div>
</div>
`
}
isWalletStored() {
const state = store.getState()
const address0 = state.app.wallet._addresses[0].address
const savedWalletData = state.user.storedWallets && state.user.storedWallets[address0]
return !!savedWalletData
}
async setSavedWalletDataJson() {
const state = store.getState()
let data
if (this.isWalletStored()) { // if the wallet is stored, we use the existing encrypted backup
const address0 = state.app.wallet._addresses[0].address
data = state.user.storedWallets[address0]
} else { // if the wallet is not stored, we generate new `saveWalletData` backup encrypted with the new password
const password = this.shadowRoot.getElementById('newWalletPassword').value
data = await state.app.wallet.generateSaveWalletData(password, state.config.crypto.kdfThreads, () => { })
}
this.savedWalletDataJson = JSON.stringify(data)
}
async showQRCode() {
await this.setSavedWalletDataJson()
let el = this.shadowRoot.getElementById('login-qr-code')
el.style.display = 'flex'
}
}
window.customElements.define('qr-login-view', QRLoginView)

View File

@ -9,6 +9,7 @@ import '@material/mwc-button'
import './account-view.js'
import './security-view.js'
import './notifications-view.js'
import './qr-login-view.js'
import { doLogout } from '../../redux/app/app-actions.js'
@ -225,6 +226,7 @@ class UserSettings extends connect(store)(LitElement) {
<ul>
<li @click=${ () => this.setSettingsView('info')} ><a class=${this.selectedView.id === 'info' ? 'active' : ''} href="javascript:void(0)">${translate("settings.account")}</a></li>
<li @click=${ () => this.setSettingsView('security')} ><a class=${this.selectedView.id === 'security' ? 'active' : ''} href="javascript:void(0)">${translate("settings.security")}</a></li>
<li @click=${ () => this.setSettingsView('qr-login')} ><a class=${this.selectedView.id === 'qr-login' ? 'active' : ''} href="javascript:void(0)">${translate("settings.qr_login_menu_item") }</a></li>
<li @click=${ () => this.setSettingsView('notification')} ><a class=${this.selectedView.id === 'notification' ? 'active' : ''} href="javascript:void(0)">${translate("settings.notifications")}</a></li>
</ul>
</div>
@ -250,6 +252,8 @@ class UserSettings extends connect(store)(LitElement) {
return html`<security-view></security-view>`;
} else if (selectedView.id === 'notification') {
return html`<notifications-view></notifications-view>`;
} else if (selectedView.id === 'qr-login') {
return html`<qr-login-view></qr-login-view>`;
}
}
@ -260,6 +264,8 @@ class UserSettings extends connect(store)(LitElement) {
return html`${translate("settings.accountsecurity")}`;
} else if (this.selectedView.id === 'notification') {
return html`UI ${translate("settings.notifications")}`;
} else if (this.selectedView.id === 'qr-login') {
return html`${translate("settings.qr_login_menu_item")}`;
}
}
@ -270,6 +276,8 @@ class UserSettings extends connect(store)(LitElement) {
return this.selectedView = { id: 'security', name: 'Account Security' }
} else if (pageId === 'notification') {
return this.selectedView = { id: 'notification', name: 'UI Notifications' }
} else if (pageId === 'qr-login') {
return this.selectedView = { id: 'qr-login', name: 'QR Login' }
}
}