on master help sign in
Merge pull request #70 from urbit/ticket-ui-fixes
0f6d696Christopher Johnson
src/components/Header.js+1−1
@@ -23,7 +23,7 @@ const Crumbs = (props) => {
23 prop-size={'sm'}
23 prop-size={'sm'}
24 key={ `history-button-${idx}` }
24 key={ `history-button-${idx}` }
25 onClick={ () => skipRoute(history.size - idx - 1) }>
25 onClick={ () => skipRoute(history.size - idx - 1) }>
26− { `${renderRoute(props, route)}` }
26+ { renderRoute(props, route) }
27 </Button>
27 </Button>
28
28
29 {
29 {
src/components/StatelessTransaction.js+15−2
@@ -15,6 +15,16 @@ const StatelessTransaction = props => {
15 const { setUserApproval, userApproval } = props
15 const { setUserApproval, userApproval } = props
16 const { canSend, handleSubmit } = props
16 const { canSend, handleSubmit } = props
17
17
18+ // setState doesn't seem to work in SetProxy/handleSubmit, so just
19+ // modifying the DOM manually here. (https://imgur.com/a/i0Qsyq1)
20+
21+ const sendTxn = (e) => {
22+ e.target.setAttribute("disabled", true);
23+ let spinner = e.target.querySelectorAll('.btn-spinner')[0];
24+ spinner.classList.remove('hide');
25+ handleSubmit()
26+ }
27+
18 const generateButtonColor =
28 const generateButtonColor =
19 Nothing.hasInstance(txn)
29 Nothing.hasInstance(txn)
20 ? 'blue'
30 ? 'blue'
@@ -150,9 +160,12 @@ const StatelessTransaction = props => {
150 prop-size={ 'xl wide' }
160 prop-size={ 'xl wide' }
151 className={ 'mt-8' }
161 className={ 'mt-8' }
152 disabled={ !canSend }
162 disabled={ !canSend }
153− onClick={ handleSubmit }
163+ onClick={ sendTxn }
154 >
164 >
165+ <span className="relative">
166+ <span className="btn-spinner hide"></span>
155− { 'Send Transaction' }
167+ { 'Send Transaction' }
168+ </span>
156 </Button>
169 </Button>
157
170
158 const sendDialogue = web3.matchWith({
171 const sendDialogue = web3.matchWith({
src/lib/router.js+4−2
@@ -1,5 +1,7 @@
1import * as ob from 'urbit-ob'
1import * as ob from 'urbit-ob'
2
2
3+import React from 'react';
4+
3import AcceptTransfer from '../views/AcceptTransfer'
5import AcceptTransfer from '../views/AcceptTransfer'
4import CancelTransfer from '../views/CancelTransfer'
6import CancelTransfer from '../views/CancelTransfer'
5import CreateGalaxy from '../views/CreateGalaxy'
7import CreateGalaxy from '../views/CreateGalaxy'
@@ -105,8 +107,8 @@ const renderRoute = (props, route) => {
105 Nothing: () => 'Wallet',
107 Nothing: () => 'Wallet',
106 Just: (wal) =>
108 Just: (wal) =>
107 wal.value instanceof EthereumWallet
109 wal.value instanceof EthereumWallet
108− ? wal.value.address
110+ ? (<span className="text-mono">{wal.value.address}</span>)
109− : addressFromSecp256k1Public(wal.value.publicKey)
111+ : (<span className="text-mono">{addressFromSecp256k1Public(wal.value.publicKey)}</span>)
110 })
112 })
111
113
112 : route === ROUTE_NAMES.MNEMONIC
114 : route === ROUTE_NAMES.MNEMONIC
src/style/extend.css+27
@@ -439,3 +439,30 @@ code {
439.pointer:hover {
439.pointer:hover {
440 cursor: pointer;
440 cursor: pointer;
441}
441}
442+
443+.hide {
444+ display: none !important;
445+}
446+
447+.btn-spinner {
448+ position: absolute;
449+ display: inline-block;
450+ width: 20px;
451+ height: 20px;
452+ left: -35px;
453+}
454+
455+.btn-spinner::after {
456+ position: absolute;
457+ width: 16px;
458+ height: 16px;
459+ bottom: 0;
460+ content: "◠";
461+ animation: spin linear 1s infinite;
462+ font-size: 20px;
463+ line-height: 20px;
464+}
465+
466+@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
467+@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
468+@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
src/style/input.css+7−7
@@ -15,6 +15,13 @@ input:-webkit-autofill {
15 -webkit-animation-fill-mode: both;
15 -webkit-animation-fill-mode: both;
16}
16}
17
17
18+input[prop-format*='innerLabel'] {
19+ padding-top: 8rem;
20+ height: 20rem;
21+ padding-left: 4rem;
22+ padding-right: 4rem;
23+}
24+
18input[prop-size='lg'] {
25input[prop-size='lg'] {
19 height: 18rem;
26 height: 18rem;
20 font-size: 5rem;
27 font-size: 5rem;
@@ -36,13 +43,6 @@ input[prop-size='sm'] {
36 padding-right: 1rem;
43 padding-right: 1rem;
37}
44}
38
45
39−input[prop-format*='innerLabel'] {
40− padding-top: 8rem;
41− height: 20rem;
42− padding-left: 4rem;
43− padding-right: 4rem;
44−}
45−
46input[prop-format*='innerLabel'][prop-size='md'] {
46input[prop-format*='innerLabel'][prop-size='md'] {
47 height: 16rem;
47 height: 16rem;
48 font-size: 4rem;
48 font-size: 4rem;
src/views/Ticket.js+21−4
@@ -25,7 +25,8 @@ class Ticket extends React.Component {
25
25
26 this.state = {
26 this.state = {
27 ticket: '',
27 ticket: '',
28− pointName: ''
28+ pointName: '',
29+ isUnlocking: false
29 }
30 }
30
31
31 this.pointPlaceholder = placeholder(4)
32 this.pointPlaceholder = placeholder(4)
@@ -53,6 +54,11 @@ class Ticket extends React.Component {
53
54
54 async walletFromTicket(ticket, pointName) {
55 async walletFromTicket(ticket, pointName) {
55 const { setWallet, setUrbitWallet } = this.props
56 const { setWallet, setUrbitWallet } = this.props
57+
58+ this.setState({
59+ isUnlocking: true
60+ });
61+
56 const urbitWallet = await kg.generateWallet({
62 const urbitWallet = await kg.generateWallet({
57 ticket: ticket,
63 ticket: ticket,
58 ship: ob.patp2dec(pointName)
64 ship: ob.patp2dec(pointName)
@@ -61,6 +67,10 @@ class Ticket extends React.Component {
61 const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH)
67 const wallet = walletFromMnemonic(mnemonic, DEFAULT_HD_PATH)
62 setWallet(wallet)
68 setWallet(wallet)
63 setUrbitWallet(Maybe.Just(urbitWallet))
69 setUrbitWallet(Maybe.Just(urbitWallet))
70+
71+ this.setState({
72+ isUnlocking: false
73+ });
64 }
74 }
65
75
66 render() {
76 render() {
@@ -99,9 +109,9 @@ class Ticket extends React.Component {
99
109
100 <TicketInput
110 <TicketInput
101 className='mono mt-8'
111 className='mono mt-8'
102− prop-size='md'
112+ prop-size='lg'
103 prop-format='innerLabel'
113 prop-format='innerLabel'
104− type='text'
114+ type='password'
105 name='ticket'
115 name='ticket'
106 placeholder={ `e.g. ${phTick}` }
116 placeholder={ `e.g. ${phTick}` }
107 value={ ticket }
117 value={ ticket }
@@ -112,9 +122,16 @@ class Ticket extends React.Component {
112 <Button
122 <Button
113 className={'mt-8'}
123 className={'mt-8'}
114 prop-size={'lg wide'}
124 prop-size={'lg wide'}
125+ disabled={this.state.isUnlocking || !Maybe.Nothing.hasInstance(wallet)}
115 // prop-color={this.buttonTriState(wallet)}
126 // prop-color={this.buttonTriState(wallet)}
116 onClick={() => this.walletFromTicket(ticket, pointName)}>
127 onClick={() => this.walletFromTicket(ticket, pointName)}>
128+
129+ <span className="relative">
130+ {this.state.isUnlocking &&
131+ <span className="btn-spinner"></span>
132+ }
117− {'Unlock Wallet →'}
133+ {'Unlock Wallet →'}
134+ </span>
118 </Button>
135 </Button>
119
136
120 <Button
137 <Button