OSDN Git Service

Merge: merge pro
[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=" currentBalances && currentBalances.length > 0">
326           <ul class="list">
327             <li class="list-item" v-for="(balance, index) in currentBalances" :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                 balance: 0,
414                 availableBalance: 0,
415                 inBtc: "0",
416                 inCny: "0",
417                 inUsd: "0"
418               }
419             ],
420             t: null
421         };
422     },
423     watch: {
424         '$route'(to, from) {
425           this.refreshBalance(this.address)
426             if (to.name.startsWith('menu')) {
427                 this.maskShow = true
428             } else if (from.name.startsWith('menu')) {
429                 this.maskShow = false
430             }
431
432             // remove transition for some page
433             this.enterActive = EnterActive
434             this.leaveActive = LeaveActive
435             if (to.name == 'transfer-confirm' || from.name == 'transfer-confirm') {
436                 this.enterActive = ''
437                 this.leaveActive = ''
438             }
439             if (from.name == 'transfer-confirm') {
440               this.setupNetwork()
441             }
442         },
443         currentAccount(newVal, oldVal) {
444             if (newVal.guid == undefined){
445               return;
446             }
447
448             // let addr
449             // if(this.netType === 'vapor'){
450             //   addr = newVal.vpAddress
451             // }else{
452             //   addr = newVal.address
453             // }
454             // this.refreshBalance(addr)
455         },
456     },
457     computed: {
458         accountBalance: function () {
459             let balance
460             const balances = this.currentBalances
461
462             if(balances && balances.length >0 ){
463                 const currency = camelize(this.currency)
464                 const arr = balances.map(o => o[currency])
465                 balance = BigNumber.sum.apply(null, arr)
466             }
467             return  Num.formatCurrency( (balance != null && balance != 0)? balance : '0.00', this.currency)
468         },
469         address: function(){
470           if(this.netType === 'vapor'){
471             const vpAddress = this.currentAccount.vpAddress
472             if(!vpAddress){
473               const bytom = this.bytom.clone();
474               return account.copy(this.currentAccount.bytom1.guid).then(accounts => {
475                 //update currentAccount
476                 bytom.currentAccount.vpAddress = accounts.address
477                 //update AccountList
478                 bytom.keychain.pairs[this.net][bytom.currentAccount.alias].vpAddress = accounts.address
479
480                 this[Actions.UPDATE_STORED_BYTOM](bytom).then(() => {
481                   // this.setupRefreshTimer()
482                 })
483
484                 return accounts.address
485               })
486             }else return vpAddress
487
488           }else{
489             return this.currentAddress
490             // return this.currentAccount.address
491           }
492         },
493         // balances: function(){
494         //   if(this.netType === 'vapor'){
495         //     return this.currentAccount.vpBalances
496         //   }else if (this.chainType === 'bytom1'){
497         //     return this.currentAccount.bytom1.balances
498         //   } else {
499         //     return this.currentAccount.balances
500         //   }
501         // },
502         ...mapState([
503           'bytom'
504         ]),
505         ...mapGetters([
506           'currentAccount',
507           'currentAddress',
508           'currentBalances',
509           'accountList',
510           'net',
511           'netType',
512           'chainType',
513           'currency'
514         ])
515     },
516     methods: {
517       img:function (symbol) {
518         let _symbol = symbol.toLowerCase();
519         if (_symbol === 'btm') {
520           _symbol = 'btm2'
521         }
522         if(this.netType === 'vapor'){
523           return `https://cdn.blockmeta.com/resources/logo/vapor/${_symbol}.png`
524         }else{
525           return `https://cdn.blockmeta.com/resources/logo/bytom/${_symbol}.png`
526         }
527       },
528       onImgError: function(event) {
529         event.target.src = require(`@/assets/img/asset/${this.netType}.png`)
530       },
531       currentBalanceAmount: function (balance) {
532         return balance[ camelize(this.currency) ]
533       },
534       shortAddress: function (add) {
535         return address.short(add)
536       },
537       formatCurrency: function (num) {
538         return Num.formatCurrency(num, this.currency)
539       },
540       itemBalance: function(assetObj){
541         const asset = assetObj.asset
542         if(asset.assetId === BTM){
543           return Num.formatNue(assetObj.balance,8)
544         }else{
545           return assetObj.balance
546         }
547       },
548         setupRefreshTimer() {
549           if(this.t){
550              clearInterval(this.t)
551           }
552           this.t = setInterval(() => {
553                 this.refreshBalance(this.address)
554             }, 10000)
555         },
556         netTypeToggle: function () {
557           const bytom = this.bytom.clone();
558           const newNetType = this.isVapor ? 'vapor' : bytom.settings.chainType === 'bytom2' ? 'bytom' : 'bytom1'
559
560           bytom.settings.netType = newNetType;
561
562           account.setupNet(`${this.net}${newNetType}`)
563           if(this.isVapor && !this.currentAccount.vpAddress){
564             account.copy(this.currentAccount.bytom1.guid).then(accounts => {
565               //update currentAccount
566               bytom.currentAccount.vpAddress = accounts.address
567               //update AccountList
568               bytom.keychain.pairs[this.net][bytom.currentAccount.alias].vpAddress = accounts.address
569
570               this[Actions.UPDATE_STORED_BYTOM](bytom).then(()=>{
571                 this.refreshBalance(this.address)
572               })
573             }).catch(error =>{
574               let e = error
575               if (error.code){
576                 e = this.$t(`error.${error.code}`)
577               }else if(error.message){
578                 e = getLang(error.message, this.language)
579               }
580               this.$toast.error(e);
581             })
582           }else{
583             this[Actions.UPDATE_STORED_BYTOM](bytom).then(()=>{
584               this.refreshBalance(this.address)
585               // this.setupRefreshTimer()
586             })
587           }
588         },
589         showQrcode: function () {
590           this.$router.push('received')
591         },
592         openMenu: function () {
593             this.$router.push('menu')
594         },
595         transferOpen: function () {
596             this.$router.push('transfer')
597         },
598         delayOpen: function () {
599             this.$router.push('delayTx')
600         },
601         crossChainOpen: function () {
602             this.$router.push('crossChain')
603         },
604         listVoteOpen: function () {
605             this.$router.push('listVote')
606         },
607         assetOpen: function (asset) {
608             this[Actions.SET_CURRENT_ASSET](asset)
609             this.$router.push('asset')
610         },
611         refreshBalance: function (address) {
612           // if(address){
613             account.balance(this.currentAddress, this)
614               .catch(error => {
615                 console.log(error);
616             });
617           // }
618         },
619       ...mapActions([
620         Actions.UPDATE_STORED_BYTOM,
621         Actions.SET_CURRENT_ASSET,
622       ])
623     },
624     mounted() {
625       this.setupRefreshTimer();
626       this.refreshBalance(this.address)
627       if (this.netType){
628         this.isVapor = this.netType =='vapor'
629       }
630     },
631     beforeDestroy() {
632       if(this.t){
633         clearInterval(this.t)
634       }
635     }
636   };
637 </script>