OSDN Git Service

fixed the delay tx list issue
[bytom/Byone.git] / src / views / home.vue
1 <style lang="scss" scoped>
2 .warp {
3     z-index: 1;
4 }
5
6 .topbar {
7     font-size: 19px;
8     display:flex;
9     justify-content: space-between;
10 }
11 .topbar .topbar-left {
12     width: 85px;
13     overflow: hidden;
14     text-overflow: ellipsis;
15     white-space: nowrap;
16     padding-top: 20px;
17     padding-left: 20px;
18 }
19 .topbar-left .btn-menu {
20     float: left;
21     margin-right: 8px;
22 }
23 .topbar-left .btn-menu i {
24     font-size: 100%;
25 }
26 .alias {
27   height: 25px;
28   font-size: 20px;
29   line-height: 28px;
30   font-weight: 600;
31 }
32
33 .topbar .topbar-right {
34   font-size: 13px;
35 }
36
37 .content {
38     margin-top: 10px;
39     text-align: center;
40     padding: 20px;
41 }
42
43 .content .token-amount {
44     font-size: 24px;
45     line-height: 35px;
46     padding-right: 17px;
47 }
48 .token-amount:first-letter {
49   color: rgba(255, 255, 255, 0.56);
50   font-size: 20px;
51 }
52 .btn-send-transfer {
53   display: flex;
54   justify-content: space-evenly;
55   text-align: center;
56   max-width: 300px;
57   height: 102px;
58   border-radius: 4px;
59   color: white;
60   font-size: 12px;
61   margin-left: auto;
62   margin-right: auto;
63
64   a:hover .icon, a:focus .icon, a:active .icon{
65     background: rgba(255, 255, 255, 0.2);
66   }
67 }
68
69 .transaction-title{
70   position:relative;
71 }
72
73
74 .transaction-title h3 {
75   font-size: 15px;
76   padding: 12px 0 16px 0px;
77   font-weight: 600;
78 }
79 .assets {
80   font-size: 15px;
81   overflow: auto;
82   flex-grow: 1;
83 }
84
85
86 .network-select{
87   text-transform: capitalize;
88 }
89
90 .btn-creation {
91     display: block;
92     width: 310px;
93     height: 48px;
94     margin: auto;
95     padding: 15px 0;
96     position: absolute;
97     bottom: 20px;
98     left: 20px;
99 }
100
101 .addr{
102   font-size: 12px;
103 }
104
105 .no-record{
106   display: block;
107 }
108
109
110 .icon{
111   width: 40px;
112   height: 40px;
113   background: rgba(255, 255, 255, 0.04);
114   border-radius: 20px;
115   display: inline-flex;
116   align-items: center;
117   justify-content: center;
118   margin-bottom: 5px;
119 }
120
121   .balance-bg{
122     height: 128px;
123
124     position:relative;
125     background: linear-gradient(228.34deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.1) 100%), #1A1A1A;
126     border-radius: 8px;
127   }
128
129   .vapor-bg{
130     background: linear-gradient(228.34deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.16) 100%), #0A42D0;
131   }
132
133   .total-asset{
134     color: rgba(255, 255, 255, 0.72);
135     font-size: 12px;
136   }
137
138
139 /* The switch - the box around the slider */
140 .switch {
141   position: relative;
142   display: inline-block;
143   width: 142px;
144   height: 36px;
145 }
146
147 /* Hide default HTML checkbox */
148 .switch input {
149   opacity: 0;
150   width: 0;
151   height: 0;
152 }
153
154 /* The slider */
155 .slider {
156   position: absolute;
157   cursor: pointer;
158   top: 0;
159   left: 0;
160   right: 0;
161   bottom: 0;
162   background-color: #F5F5F5;
163   -webkit-transition: .4s;
164   transition: .4s;
165 }
166
167 .slider:before {
168   position: absolute;
169   content: "";
170   height: 28px;
171   width: 67px;
172   left: 4px;
173   bottom: 4px;
174   background-color: white;
175   box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.04);
176   -webkit-transition: .4s;
177   transition: .4s;
178 }
179
180 /*input:checked + .slider {*/
181   /*background-color: #2196F3;*/
182 /*}*/
183
184 /*input:focus + .slider {*/
185   /*box-shadow: 0 0 1px #2196F3;*/
186 /*}*/
187
188 input:checked + .slider:before {
189   -webkit-transform: translateX(67px);
190   -ms-transform: translateX(67px);
191   transform: translateX(67px);
192 }
193
194 /* Rounded sliders */
195 .slider.round {
196   border-radius: 34px;
197 }
198
199 .slider.round:before {
200   border-radius: 34px;
201 }
202
203 .slider-label{
204   position: absolute;
205   justify-content: space-around;
206   width: 141px;
207   height: 36px;
208   align-items: center;
209   top: 0;
210   color: rgba(0, 0, 0, 0.24);
211 }
212
213 .slider-label>div.active{
214   color: rgba(0, 0, 0, 0.64);
215 }
216
217
218
219   .symbol{
220     display: flex;
221     align-items: center;
222   }
223
224   .warp-menu{
225     display: flex;
226     flex-direction: column;
227   }
228
229   @media screen and (min-width: 768px) {
230       .balance-bg{
231         display: flex;
232         align-items: center;
233         padding: 20px 40px;
234
235         .amount{
236           text-align:left;
237         }
238
239         .total-asset{
240           font-size:14px;
241         }
242         .token-amount{
243           font-size: 36px;
244           margin-top: 5px;
245         }
246
247         .token-amount:first-letter {
248           font-size: 28px;
249         }
250
251         .btn-send-transfer{
252           align-items: center;
253           margin-right: inherit;
254           width: 372px;
255         }
256       }
257
258
259     }
260   .delay-btn{
261     position: absolute;
262     background: #F5F5F5;
263     border-radius: 16px 0px 0px 16px;
264     right: -20px;
265     color: rgba(0, 0, 0, 0.88);
266     font-size: 12px;
267     padding: 4px 10px;
268     top: 8px;
269   }
270   .icon_SBell{
271     font-size: 16px;
272     margin-right: 4px;
273     vertical-align: middle;
274   }
275 </style>
276
277 <template>
278     <div class="warp-menu">
279         <section>
280             <div class="topbar">
281                 <div v-if="address!=undefined" >
282                   <span class="alias color-black">{{currentAccount.alias}}</span>
283                 </div>
284                 <div class="topbar-right">
285                   <label class="switch">
286                     <input type="checkbox" v-model="isVapor" @change="netTypeToggle">
287                     <span class="slider round"></span>
288                     <div class="d-flex slider-label">
289                       <div :class="{ active: !isVapor }" >{{ $t('main.bytom') }}</div>
290                       <div :class="{ active: isVapor }">{{ $t('main.vapor') }}</div>
291                     </div>
292                   </label>
293                 </div>
294             </div>
295             <div :class="['content balance-bg',{ 'vapor-bg': isVapor }]">
296               <div class="amount color-white">
297                   <div class="total-asset">{{ $t('main.totalAsset') }}</div>
298                   <div class="token-amount">
299                       {{accountBalance}}
300                   </div>
301               </div>
302               <div class="btn-send-transfer">
303
304                 <a  @click="transferOpen">
305                   <i class="icon iconfont icon_send"></i>
306                   <div>{{ $t('main.send') }}</div>
307                 </a>
308                 <a  @click="showQrcode">
309                   <i class="icon iconfont icon_recvice"></i>
310                   <div>{{ $t('main.receive') }}</div>
311                 </a>
312                 <a class="color-white" href="https://ofmf.bymov.io/cross-chain" target="_blank">
313                   <i class="icon iconfont icon_cross"></i>
314                   <div>{{ $t('main.crossChain') }}</div>
315                 </a>
316               </div>
317             </div>
318
319         </section>
320       <section v-if="address!=undefined" class="transaction-title">
321         <h3 class="color-black">{{ $t('main.asset') }}</h3>
322         <a class="delay-btn" @click="delayOpen"><i class="iconfont icon_SBell"></i>{{ $t('delayTx.title') }}</a>
323       </section>
324       <section class="assets">
325         <div v-if=" balances && balances.length > 0">
326           <ul class="list">
327             <li class="list-item" v-for="(balance, index) in balances" :key="index" @click="assetOpen(balance)">
328               <div class="symbol" v-if="balance.asset.symbol!== 'Asset'">
329                 <img :src="img(balance.asset.symbol)" alt="" class="c-icon"  v-on:error="onImgError">
330                 <div class="uppercase">
331                   {{balance.asset.symbol}}
332                 </div>
333               </div>
334               <div v-else>
335                 <div>
336                   Asset
337                 </div>
338
339                 <div class="addr color-grey uppercase">{{ shortAddress(balance.asset.assetId) }}</div>
340               </div>
341
342               <div class="text-align-right">
343                 <div class="value">{{ itemBalance(balance) }}</div>
344                 <div class="addr color-grey">{{ formatCurrency(currentBalanceAmount(balance)) }}</div>
345               </div>
346
347             </li>
348           </ul>
349         </div>
350         <div v-else>
351           <ul class="list">
352             <li class="list-item" v-for="(asset, index) in defaultBalances" :key="index" @click="assetOpen(asset)">
353
354               <div class="symbol">
355                 <img :src="img(asset.asset.symbol)" alt="" class="c-icon"  v-on:error="onImgError">
356
357                 <div class="uppercase">
358                   {{asset.asset.symbol}}
359                 </div>
360
361               </div>
362
363               <div class=" text-align-right">
364                 <div class="value">{{ itemBalance(asset) }}</div>
365                 <div class="addr color-grey">{{ formatCurrency(asset[ currency ]) }}</div>
366               </div>
367
368             </li>
369           </ul>
370         </div>
371       </section>
372
373         <!-- child page -->
374         <div class="mask" v-show="maskShow"></div>
375         <transition :enter-active-class="enterActive" :leave-active-class="leaveActive">
376             <router-view></router-view>
377         </transition>
378
379     </div>
380 </template>
381
382 <script>
383 import address from "@/utils/address";
384 import account from "@/models/account";
385 import { camelize } from "@/utils/utils";
386 import { BTM } from "@/utils/constants";
387 import { mapActions, mapGetters, mapState } from 'vuex'
388 import * as Actions from '@/store/constants';
389 import _ from 'lodash';
390 import { Number as Num } from "@/utils/Number"
391 import BigNumber from "bignumber.js"
392 import getLang from "@/assets/language/sdk";
393
394
395 const EnterActive = 'animated faster fadeInLeft';
396 const LeaveActive = 'animated faster fadeOutLeft';
397 export default {
398     name: "",
399     data() {
400         return {
401             isVapor: false,
402             maskShow: false,
403             enterActive: EnterActive,
404             leaveActive: LeaveActive,
405             defaultBalances: [
406               {
407                 asset:{
408                   assetId: BTM,
409                   name: "Bytom",
410                   symbol: "BTM",
411                   decimals: 8
412                 } ,
413                 availableBalance: 0,
414                 inBtc: "0",
415                 inCny: "0",
416                 inUsd: "0"
417               }
418             ],
419             t: null
420         };
421     },
422     watch: {
423         '$route'(to, from) {
424             if (to.name.startsWith('menu')) {
425                 this.maskShow = true
426             } else if (from.name.startsWith('menu')) {
427                 this.maskShow = false
428             }
429
430             // remove transition for some page
431             this.enterActive = EnterActive
432             this.leaveActive = LeaveActive
433             if (to.name == 'transfer-confirm' || from.name == 'transfer-confirm') {
434                 this.enterActive = ''
435                 this.leaveActive = ''
436             }
437             if (from.name == 'transfer-confirm') {
438               this.setupNetwork()
439             }
440         },
441         currentAccount(newVal, oldVal) {
442             if (newVal.guid == undefined){
443               return;
444             }
445
446             let addr
447             if(this.netType === 'vapor'){
448               addr = newVal.vpAddress
449             }else{
450               addr = newVal.address
451             }
452             this.refreshBalance(addr)
453         },
454     },
455     computed: {
456         accountBalance: function () {
457             let balance
458             const balances = this.balances
459
460             if(balances && balances.length >0 ){
461                 const currency = camelize(this.currency)
462                 const arr = balances.map(o => o[currency])
463                 balance = BigNumber.sum.apply(null, arr)
464             }
465             return  Num.formatCurrency( (balance != null && balance != 0)? balance : '0.00', this.currency)
466         },
467         address: function(){
468           if(this.netType === 'vapor'){
469             const vpAddress = this.currentAccount.vpAddress
470             if(!vpAddress){
471               const bytom = this.bytom.clone();
472               return account.copy(this.currentAccount.guid).then(accounts => {
473                 //update currentAccount
474                 bytom.currentAccount.vpAddress = accounts.address
475                 //update AccountList
476                 bytom.keychain.pairs[this.net][bytom.currentAccount.alias].vpAddress = accounts.address
477
478                 this[Actions.UPDATE_STORED_BYTOM](bytom).then(() => {
479                   this.setupRefreshTimer()
480                 })
481
482                 return accounts.address
483               })
484             }else return vpAddress
485
486           }else{
487             return this.currentAccount.address
488           }
489         },
490         balances: function(){
491           if(this.netType === 'vapor'){
492             return this.currentAccount.vpBalances
493           }else{
494             return this.currentAccount.balances
495           }
496         },
497         ...mapState([
498           'bytom'
499         ]),
500         ...mapGetters([
501           'currentAccount',
502           'accountList',
503           'net',
504           'netType',
505           'currency'
506         ])
507     },
508     methods: {
509       img:function (symbol) {
510         const _symbol = symbol.toLowerCase();
511         if(this.netType === 'vapor'){
512           return `https://cdn.blockmeta.com/resources/logo/vapor/${_symbol}.png`
513         }else{
514           return `https://cdn.blockmeta.com/resources/logo/bytom/${_symbol}.png`
515         }
516       },
517       onImgError: function(event) {
518         event.target.src = require(`@/assets/img/asset/${this.netType}.png`)
519       },
520       currentBalanceAmount: function (balance) {
521         return balance[ camelize(this.currency) ]
522       },
523       shortAddress: function (add) {
524         return address.short(add)
525       },
526       formatCurrency: function (num) {
527         return Num.formatCurrency(num, this.currency)
528       },
529       itemBalance: function(assetObj){
530         const asset = assetObj.asset
531         if(asset.assetId === BTM){
532           return Num.formatNue(assetObj.balance,8)
533         }else{
534           return assetObj.balance
535         }
536       },
537         setupRefreshTimer() {
538           if(this.t){
539              clearInterval(this.t)
540           }
541           this.t = setInterval(() => {
542                 this.refreshBalance(this.address)
543             }, 10000)
544         },
545         netTypeToggle: function () {
546           const bytom = this.bytom.clone();
547           const newNetType = this.isVapor? 'vapor':'bytom'
548
549           bytom.settings.netType = newNetType;
550
551           account.setupNet(`${this.net}${newNetType}`)
552           if(this.isVapor && !this.currentAccount.vpAddress){
553             account.copy(this.currentAccount.guid).then(accounts => {
554               //update currentAccount
555               bytom.currentAccount.vpAddress = accounts.address
556               //update AccountList
557               bytom.keychain.pairs[this.net][bytom.currentAccount.alias].vpAddress = accounts.address
558
559               this[Actions.UPDATE_STORED_BYTOM](bytom).then(()=>{
560                 this.setupRefreshTimer()
561               })
562             }).catch(error =>{
563               let e = error
564               if (error.code){
565                 e = this.$t(`error.${error.code}`)
566               }else if(error.message){
567                 e = getLang(error.message, this.language)
568               }
569               this.$toast.error(e);
570             })
571           }else{
572             this[Actions.UPDATE_STORED_BYTOM](bytom).then(()=>{
573               this.setupRefreshTimer()
574             })
575           }
576         },
577         showQrcode: function () {
578           this.$router.push('received')
579         },
580         openMenu: function () {
581             this.$router.push('menu')
582         },
583         transferOpen: function () {
584             this.$router.push('transfer')
585         },
586         delayOpen: function () {
587             this.$router.push('delayTx')
588         },
589         crossChainOpen: function () {
590             this.$router.push('crossChain')
591         },
592         listVoteOpen: function () {
593             this.$router.push('listVote')
594         },
595         assetOpen: function (asset) {
596             this[Actions.SET_CURRENT_ASSET](asset)
597             this.$router.push('asset')
598         },
599         refreshBalance: function (address) {
600           if(address){
601             account.balance(address, this)
602               .catch(error => {
603                 console.log(error);
604             });
605           }
606         },
607       ...mapActions([
608         Actions.UPDATE_STORED_BYTOM,
609         Actions.SET_CURRENT_ASSET,
610       ])
611     },
612     mounted() {
613       this.setupRefreshTimer();
614       this.refreshBalance(this.address)
615       if (this.netType){
616         this.isVapor = this.netType =='vapor'
617       }
618     },
619     beforeDestroy() {
620       if(this.t){
621         clearInterval(this.t)
622       }
623     }
624   };
625 </script>