diff --git a/package-lock.json b/package-lock.json index 2e6fc37..a3fb6e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wallet", - "version": "1.23.1", + "version": "1.23.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wallet", - "version": "1.23.1", + "version": "1.23.2", "license": "GPL", "dependencies": { "@chenfengyuan/vue-qrcode": "^2.0.0", diff --git a/package.json b/package.json index 8ea3ee2..0ff6d2c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wallet", - "version": "1.23.1", + "version": "1.23.2", "description": "Web wallet for managing $EDGE", "private": true, "license": "GPL", diff --git a/src/components/tx/SendModal.vue b/src/components/tx/SendModal.vue index fd0d803..8521bae 100644 --- a/src/components/tx/SendModal.vue +++ b/src/components/tx/SendModal.vue @@ -11,13 +11,32 @@
- +
+ +
+
My wallets
+ +
+
{{error.$message}}
@@ -187,7 +206,7 @@ import Modal from '../Modal.vue' import Radio from '../Radio.vue' import { helpers } from '@vuelidate/validators' import { mapState } from 'vuex' -import { parseAmount } from '../../utils/form' +import { parseAmount, truncateAddress } from '../../utils/form' import useVuelidate from '@vuelidate/core' const memoRegexp = /^[a-zA-Z0-9\s-]{0,32}$/ @@ -216,7 +235,9 @@ export default { passwordError: '', completedTx: null, - submitError: '' + submitError: '', + + showRecipientDropdown: false } }, validations() { @@ -239,7 +260,18 @@ export default { } }, computed: { - ...mapState(['address', 'balance', 'nextNonce']), + ...mapState(['address', 'balance', 'nextNonce', 'wallets', 'activeWalletId']), + otherWallets() { + return this.wallets.filter(w => w.id !== this.activeWalletId) + }, + filteredWallets() { + const query = this.recipient.trim().toLowerCase() + if (!query) return this.otherWallets + return this.otherWallets.filter(w => + w.name.toLowerCase().includes(query) || + w.address.toLowerCase().includes(query) + ) + }, amountParsed() { return parseAmount(this.amount) }, @@ -266,6 +298,21 @@ export default { this.reset() this.close() }, + onRecipientFocus() { + this.showRecipientDropdown = true + }, + onRecipientEsc() { + this.showRecipientDropdown = false + }, + onRecipientBlur() { + // Small delay so mousedown on dropdown item fires before hide + setTimeout(() => { this.showRecipientDropdown = false }, 150) + }, + selectRecipient(wallet) { + this.recipient = wallet.address + this.showRecipientDropdown = false + }, + truncateAddress, async checkPassword() { this.v$.password.$reset() if (await storage.comparePassword(this.password)) { @@ -298,6 +345,7 @@ export default { this.completedTx = null this.submitError = '' + this.showRecipientDropdown = false this.v$.$reset() }, @@ -370,4 +418,44 @@ export default { color: #0ecc5f; padding-left: 10px; } + +.recipient-input-wrap { + position: relative; +} + +.recipient-suggestions { + @apply absolute left-0 right-0 rounded-lg z-20 py-6; + top: 100%; + margin-top: 6px; + max-height: 160px; + overflow-y: auto; + background: #1d1d1d; + border: 1px solid rgba(255, 255, 255, 0.15); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.8); +} + +.recipient-suggestions__header { + @apply px-12 text-gray-400; + padding-top: 4px; + padding-bottom: 8px; + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.recipient-suggestions__item { + @apply flex items-center justify-between w-full px-12 py-10 text-gray transition-colors cursor-pointer; + @apply hover:text-white hover:bg-gray-700 hover:bg-opacity-25; + background: none; + border: none; + font-size: 13px; +} + +.recipient-suggestions__name { + @apply font-medium text-white text-sm leading-tight; +} + +.recipient-suggestions__address { + @apply text-sm2 text-gray-400 leading-tight; +} diff --git a/src/components/wallet/WalletIndicator.vue b/src/components/wallet/WalletIndicator.vue index 4b90dde..e8729a9 100644 --- a/src/components/wallet/WalletIndicator.vue +++ b/src/components/wallet/WalletIndicator.vue @@ -60,6 +60,7 @@