Ver código fonte

Merge branch 'master' of https://git.yishihui.com/DeNet/de-net

zhangwei 2 anos atrás
pai
commit
a5692460ef
44 arquivos alterados com 1060 adições e 175 exclusões
  1. 1 0
      .gitignore
  2. 30 0
      buildTestApp.sh
  3. 1 0
      package.json
  4. BIN
      src/assets/img/icon-box2.png
  5. 1 0
      src/assets/svg/icon-create-nfts.svg
  6. 5 0
      src/assets/svg/icon-transaction-s.svg
  7. 8 0
      src/http/configAPI.js
  8. 6 1
      src/http/fetch.js
  9. 8 0
      src/http/nft.js
  10. 6 1
      src/iframe/publish.js
  11. 31 0
      src/log-center/autoLog/click.js
  12. 23 0
      src/log-center/autoLog/index.js
  13. 50 0
      src/log-center/autoLog/show.js
  14. 5 0
      src/log-center/logEnum.js
  15. 10 4
      src/log-center/logger.js
  16. 4 3
      src/logic/background/denet.js
  17. 13 12
      src/logic/background/twitter.js
  18. 19 0
      src/logic/content/twitter.js
  19. 4 3
      src/manifest.json
  20. 6 1
      src/router/popup.js
  21. 6 1
      src/uilts/chromeExtension.js
  22. 9 0
      src/uilts/help.js
  23. 114 0
      src/view/components/nft-card.vue
  24. 29 2
      src/view/components/popup-transactions.vue
  25. 29 7
      src/view/iframe/buy-nft/buy/home.vue
  26. 14 2
      src/view/iframe/buy-nft/buy/open-box.vue
  27. 16 3
      src/view/iframe/buy-nft/buy/pay.vue
  28. 59 5
      src/view/iframe/nft/card.vue
  29. 2 2
      src/view/iframe/publish/components/preview-card.vue
  30. 59 2
      src/view/iframe/publish/give-dialog.vue
  31. 5 1
      src/view/iframe/publish/tool-box/child/editor.vue
  32. 5 5
      src/view/iframe/publish/tool-box/child/preview.vue
  33. 3 3
      src/view/iframe/publish/tool-box/index.vue
  34. 1 1
      src/view/iframe/tool-box/card.vue
  35. 0 1
      src/view/popup/components/tabbar.vue
  36. 29 3
      src/view/popup/currency-detail.vue
  37. 3 1
      src/view/popup/setting/index.vue
  38. 0 1
      src/view/popup/tabbar-page/index.vue
  39. 25 3
      src/view/popup/tabbar-page/message/index.vue
  40. 73 24
      src/view/popup/tabbar-page/more/index.vue
  41. 45 80
      src/view/popup/tabbar-page/nft/detail.vue
  42. 3 2
      src/view/popup/tabbar-page/nft/index.vue
  43. 300 0
      src/view/popup/tabbar-page/nft/transfer.vue
  44. 0 1
      src/view/popup/tabbar-page/wallter/popup.vue

+ 1 - 0
.gitignore

@@ -21,3 +21,4 @@ pnpm-debug.log*
 *.njsproj
 *.sln
 *.sw?
+*.zip

+ 30 - 0
buildTestApp.sh

@@ -0,0 +1,30 @@
+
+#! /bin/bash
+env=$1
+if [ ! $env ]; then  
+    env='test'
+fi 
+
+echo '当前打包环境: '$env
+
+read -p "请输入压缩后的包名称(直接回车将使用 test_版本号 命名)" libname
+
+if [ ! $libname ]; then  
+    JQ_EXEC=`which jq`
+    FILE_PATH=./src/manifest.json
+    libname=test_$(cat $FILE_PATH | ${JQ_EXEC} .version | sed 's/\"//g')
+fi  
+
+echo '打包文件名: '$libname
+
+echo '----------------开始打包--------------------'
+
+yarn build-$env
+
+echo '----------------打包结束--------------------'
+
+zip -r $libname.zip dist/*
+
+open ./
+open $libname.zip -R
+

+ 1 - 0
package.json

@@ -5,6 +5,7 @@
   "scripts": {
     "serve": "vue-cli-service serve",
     "build-test": "vue-cli-service build --mode development",
+    "build-local": "sh buildTestApp.sh",
     "build-pre": "vue-cli-service build --mode pre",
     "build-prod": "vue-cli-service build --mode production",
     "lint": "vue-cli-service lint",

BIN
src/assets/img/icon-box2.png


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 0
src/assets/svg/icon-create-nfts.svg


+ 5 - 0
src/assets/svg/icon-transaction-s.svg

@@ -0,0 +1,5 @@
+<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="17" height="17" rx="8.5" transform="matrix(-1 0 0 1 17 0)" fill="#4CD6D6"/>
+<path d="M9.6611 5.16894L10.7911 4.5L12.6981 7.68105H4.5V6.37508H10.3846L9.6611 5.16688V5.16894Z" fill="white"/>
+<path d="M6.4148 12.4985L7.54684 11.8316L7.54581 11.8295L6.8213 10.6213H12.7079V9.31641H4.50781L6.4148 12.4985Z" fill="white"/>
+</svg>

+ 8 - 0
src/http/configAPI.js

@@ -20,12 +20,20 @@ const page = {
 	development: 'https://testh5.denetme.net'
 }
 
+const website = {
+	production: "https://denet.me",
+	pre: "https://pre.denet.me",
+	development: 'https://test.denet.me'
+}
+
 export const baseAPIUrl = api[process.env.NODE_ENV] + '/denet'
 
 export const logAPIUrl = logApi[process.env.NODE_ENV] + '/log-center'
 
 export const pageUrl = page[process.env.NODE_ENV]
 
+export const websiteUrl = website[process.env.NODE_ENV]
+
 export const discordAuthRedirectUri = `${pageUrl}/auth/discordCallback`;
 
 export const faceShareRedirectUrl = `${pageUrl}/facebook/shareCallback`;

+ 6 - 1
src/http/fetch.js

@@ -61,7 +61,12 @@ export async function commonFetch({ url = '', method = 'POST' , params = {}, bas
                 resolve(data);
             })
             .catch((error) => {
-                reject({url: _url, error: error, requestParams: bodyObj});
+                if(!error) {
+                    error = {}
+                }
+                reject({url: _url, 
+                        error: { message: error.message, stack: error.stack }, 
+                        requestParams: bodyObj });
             });
     })
 }

+ 8 - 0
src/http/nft.js

@@ -71,4 +71,12 @@ export function getTwitterNftGroupInfo(params) {
         method: 'post',
         data: params
     })
+}
+
+export function transferRequest(params) {
+    return service({
+        url: `/nft/transfer/request`,
+        method: 'post',
+        data: params
+    })
 }

+ 6 - 1
src/iframe/publish.js

@@ -3,7 +3,9 @@ import App from '@/view/iframe/publish/publish.vue'
 
 import "ant-design-vue/dist/antd.css"; // or 'ant-design-vue/dist/antd.less'
 
-import {Button,message,Tooltip, Switch} from "ant-design-vue";
+import { Button, message, Tooltip, Switch } from "ant-design-vue";
+
+import AutoLog from '@/log-center/autoLog';
 
 message.config({
     top: `10px`,
@@ -17,7 +19,10 @@ app.use(Button);
 app.use(Tooltip);
 app.use(message);
 app.use(Switch);
+app.use(AutoLog);
+
 
 import CoutomSentry from "@/uilts/sentry.js"
 CoutomSentry.initVue(app)
 app.mount('#app');
+

+ 31 - 0
src/log-center/autoLog/click.js

@@ -0,0 +1,31 @@
+// 点击埋点自定义属性
+
+import { reportLog } from '../logger';
+import { getTargetElementWhenClick } from '@/uilts/help';
+import Report from "@/log-center/log";
+
+let clickDataMap = new Map();
+
+const clickHandle = (e) => { 
+    const target = getTargetElementWhenClick(e);
+    const logData = clickDataMap.get(target?.denetClickLogkey);
+    return logData && reportLog({
+        businessType: Report.businessType.buttonClick,
+        ...logData
+    })
+}
+
+const clickLog =  {
+    mounted: (el, binding) => { 
+        const { value } = binding;
+        el.denetClickLogkey = el.denetClickLogkey || Math.random().toString(36).slice(-6);
+        clickDataMap.set(el.denetClickLogkey, value);
+        el.addEventListener('click', clickHandle,true)
+    },
+    unmounted(el) { 
+        // remove EventListener
+        el.removeEventListener('click', clickHandle, true)
+    }
+}
+
+export default clickLog;

+ 23 - 0
src/log-center/autoLog/index.js

@@ -0,0 +1,23 @@
+// 埋点插件
+
+import { showReportDialog } from '@sentry/vue';
+import clickLog from './click';
+import ShowLogObserver from './show';
+
+const AutoLog = {};
+
+AutoLog.install = (app) => { 
+    app.directive('click-log', clickLog);
+    app.directive('show-log', {
+        mounted(el, binding) {
+            // 加载阶段设置随机key标记当前元素
+            el.denetShowLogkey = el.denetShowLogkey || Math.random().toString(36).slice(-6);
+            ShowLogObserver.add(el, binding);
+        },
+        unmounted(el) {
+            ShowLogObserver.remove(el);
+        },
+    });
+}
+
+export default AutoLog;

+ 50 - 0
src/log-center/autoLog/show.js

@@ -0,0 +1,50 @@
+import { reportLog } from '../logger';
+import { getActiveKeyAfterClick } from '@/uilts/help';
+import Report from "@/log-center/log"
+
+// 每个窗口共享一个Observer实例
+class ShowLogObserver { 
+    constructor() { 
+        this._observe = null;
+        this.showLogMap = new Map();
+        this.init();
+    }
+
+    init() {
+        this._observe = new IntersectionObserver((entries, observer) => {
+            entries.forEach((entry) => {
+                if (entry.isIntersecting) {
+                    this.report(entry);
+                    // show-log-once  ===  '1' &&  曝光之后取消观察
+                    if (entry?.target?.getAttribute('show-log-once') === '1') { 
+                        this.remove(entry.target);
+                    }
+                }
+            })
+        }, {
+            root: null,
+            rootMargin: '0px',
+            threshold: 1
+        })
+    }
+
+    remove(el) { 
+        this._observe.unobserve(el);
+        this.showLogMap.delete(el.denetShowLogkey);
+    }
+
+    add(el, binding) { 
+        this._observe.observe(el);
+        this.showLogMap.set(el.denetShowLogkey, binding.value)
+    }
+
+    report(el) { 
+        const logData = this.showLogMap.get(el?.target?.denetShowLogkey);
+        return logData && reportLog({
+            businessType: Report.businessType.pageView,
+            ...logData
+        })
+    }
+}
+
+export default new ShowLogObserver();

+ 5 - 0
src/log-center/logEnum.js

@@ -52,6 +52,9 @@ export const objectType = {
     background_function_catch: 'background-function-catch',
     // background 文件chrome 函数 try
     background_function_try:'background-function-try',
+    // create Nft
+    create_nfts_button: 'create-nfts-button',
+    confirm_transfer_button: 'confirm-transfer-button',
 }
 
 export const pageSource = {
@@ -66,7 +69,9 @@ export const pageSource = {
     denetWithdrawForm: "denet-withdraw-form",
     denetWithdrawConfirm: "denet-withdraw-confirm",
     denetTopupSelector: "denet-topup-selector",
+    denetMorePage: "denet-more-page",
     denetSelector: "denet-selector",
+    denetNftTransferPage: "denet-nft-transfer-page",
     // 待开红包页
     pending_page: 'pending-page',
     // 已领取任务页

+ 10 - 4
src/log-center/logger.js

@@ -16,13 +16,13 @@ export async function reportLog(eventData = {}, extParams = {}) {
     if (!mid) {
         mid = await getChromeStorage('mid') || '';
     }
+    let isMobile = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i);
+    let platform = isMobile ? `mobile` : `pc`;
+    let browser = getBrowser();
     if (chrome && chrome.tabs) {
         chrome.tabs.getCurrent((tab) => {
             if (tab && tab.url) {
-                let isMobile = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i);
                 let { url = '' } = tab;
-                let platform = isMobile ? `mobile` : `pc`;
-                let browser = getBrowser();
                 let extData = {
                     url,
                     platform,
@@ -32,7 +32,13 @@ export async function reportLog(eventData = {}, extParams = {}) {
                 }
                 paramsPretreatmentAndRequest(logType.denet, extData, extParams)
             }else{
-                paramsPretreatmentAndRequest(logType.denet, eventData, extParams)
+                let extData = {
+                    platform,
+                    browser,
+                    twitterId: userInfo && userInfo.nickName || '',
+                    ...eventData,
+                }
+                paramsPretreatmentAndRequest(logType.denet, extData, extParams)
             }
         })
     } else {

+ 4 - 3
src/logic/background/denet.js

@@ -6,10 +6,11 @@ export const closeAchPayNoticeHandler = async () => {
     if(res.url.startsWith(payAchNoticeUrl)) {
         chrome.tabs.remove(
             res.id, () => {
-                getChromeStorage('achPayInfo', (res) => {
+                getChromeStorage('achPayInfo', (result) => {
+                    let {tab} = result || {};
                     chrome.storage.local.remove("achPayInfo");
-                    if(res && res.tab) {
-                        chrome.tabs.highlight({ windowId: res.tab.windowId, tabs: res.tab.index })
+                    if(tab) {
+                        chrome.tabs.highlight({ windowId: tab.windowId, tabs: tab.index })
                     }
                 })
             }

+ 13 - 12
src/logic/background/twitter.js

@@ -1,5 +1,5 @@
 import { fetchTtwitterRequestToken, fetchTwitterLogin, fetchTwitterShortUrl, fetchAllMessageInfo, fetchReadTaskAllMsg, getDiscordUserInfo, fetchGetTwitterNftPostPre, fetchPublish, fetchGetAllUnReadNotices } from '@/logic/background/fetch/twitter.js'
-import { LANDING_PAGE, LANDING_PAGE_MID, setChromeStorage, setChromeCookie, getChromeCookie, getChromeStorage, removeChromeCookie, LANDING_PAGE_JUMP_INFO } from '@/uilts/chromeExtension.js'
+import { LANDING_PAGE, WEBSITE_USER_INFO, LANDING_PAGE_MID, setChromeStorage, setChromeCookie, getChromeCookie, getChromeStorage, removeChromeCookie, LANDING_PAGE_JUMP_INFO } from '@/uilts/chromeExtension.js'
 import { guid } from '@/uilts/help.js'
 import { discordAuthRedirectUri } from '@/http/configAPI'
 import { setContentMessage } from '@/logic/background/help.js'
@@ -88,6 +88,7 @@ export function twitterPinLoginCode(sender, code) {
         fetchTwitterLogin(authToken, consumerKey, code, receivedIds).then(res => {
             if (res.code == 0) {
                 setChromeStorage({ userInfo: JSON.stringify(res.data) })
+                setChromeCookie(WEBSITE_USER_INFO, res.data)
 
                 sendActivetabMessage({
                     actionType: 'BG_LOGIN_SET_USERINFO_CB'
@@ -256,14 +257,14 @@ export function onInstalledCreateTab() {
             Report.reportLog({
                 objectType: Report.objectType.chrome_extension_installed,
                 funcName: 'onInstalledCreateTab',
-                postId: res.postId || ''
+                postId: res?.postId || ''
             })
         }, 5000)
-
+        let url = 'https://twitter.com/search?q=%23denet'
         // jump_info
         if (!res || !res.jump_type) {
             chrome.tabs.create({
-                url: "https://twitter.com",
+                url
             });
             return
         }
@@ -273,7 +274,7 @@ export function onInstalledCreateTab() {
             case 'red_packet':
                 if (res && res.postNickName && res.srcContentId) {
                     created_detail = true
-                    let url = `https://twitter.com/${res.postNickName}/status/${res.srcContentId}`
+                    url = `https://twitter.com/${res.postNickName}/status/${res.srcContentId}`
                     chrome.tabs.create({
                         url
                     });
@@ -283,17 +284,17 @@ export function onInstalledCreateTab() {
             case 'luck_draw':
                 if (res && res.postNickName && res.srcContentId) {
                     created_detail = true
-                    let url = `https://twitter.com/${res.postNickName}/status/${res.srcContentId}`
+                    url = `https://twitter.com/${res.postNickName}/status/${res.srcContentId}`
                     chrome.tabs.create({
                         url
                     });
                 }
                 break
             // NFT
-            case 'ntf_info':
+            case 'nft_info':
                 if (res && res.twitterAccount && res.nftProjectId) {
                     created_detail = true
-                    let url = `https://twitter.com/${res.twitterAccount}`
+                    url = `https://twitter.com/${res.twitterAccount}`
                     chrome.tabs.create({
                         url
                     });
@@ -310,8 +311,8 @@ export function onInstalledCreateTab() {
                         groupTabData: JSON.stringify({
                             deTabVal: 'deGroupTab'
                         })
-                    }, (res) => {
-                        let url = `https://twitter.com/${res.twitterAccount}`
+                    }, (response) => {
+                        url = `https://twitter.com/${res.twitterAccount}`
                         chrome.tabs.create({
                             url
                         });
@@ -322,7 +323,7 @@ export function onInstalledCreateTab() {
             case 'tool_box':
                 if (res && res.postNickName && res.srcContentId) {
                     created_detail = true
-                    let url = `https://twitter.com/${res.postNickName}/status/${res.srcContentId}`
+                    url = `https://twitter.com/${res.postNickName}/status/${res.srcContentId}`
                     chrome.tabs.create({
                         url
                     });
@@ -332,7 +333,7 @@ export function onInstalledCreateTab() {
 
         if (created_detail == false) {
             chrome.tabs.create({
-                url: "https://twitter.com",
+                url
             });
         }
 

+ 19 - 0
src/logic/content/twitter.js

@@ -927,6 +927,7 @@ export function init() {
     }
 
     if (window.location.host.includes('twitter.com')) {
+        // onPageVisbile();
         renderDom();
         showNFTCard()
         showNFTGroupIcon()
@@ -970,6 +971,24 @@ export function init() {
     });
 }
 
+function onPageVisbile() {
+    document.addEventListener('visibilitychange', function () {
+        let isHidden = document.hidden;
+        if (!isHidden) {
+            depositUSShowPopupPage();
+        }
+    });
+}
+
+const depositUSShowPopupPage = async () => {
+    let {form = '', path} = await getChromeStorage('achPayData') || {};
+    if(form == 'popupPage') {
+        showPopupPage({path});
+        chrome.storage.local.remove("achPayData");
+    }
+}
+
+
 function checkHasSliderDeBtn() {
     let deBtn = document.getElementById('de-btn');
     let deBtn3 = document.getElementById('de-btn3');

+ 4 - 3
src/manifest.json

@@ -2,8 +2,8 @@
     "manifest_version": 3,
     "name": "DeNet",
     "description": "Growing more twitter followers with Denet",
-    "version": "1.1.5.1",
-    "denet_app_version_code": "16",
+    "version": "1.1.6",
+    "denet_app_version_code": "17",
     "background": {
         "service_worker": "/js/background.js"
     },
@@ -99,7 +99,8 @@
                 "/iframe/tool-box-guide.html",
                 "/iframe/tool-box.html",
                 "/iframe/test.html",
-                "/iframe/ach-cashier.html"
+                "/iframe/ach-cashier.html",
+                "/img/icon-denet-logo.svg"
             ],
             "matches": [
                 "<all_urls>"

+ 6 - 1
src/router/popup.js

@@ -7,7 +7,7 @@ import Message from '@/view/popup/tabbar-page/message/index.vue'
 import More from '@/view/popup/tabbar-page/more/index.vue'
 
 import NFTDetail  from '@/view/popup/tabbar-page/nft/detail.vue'
-
+import NFTTransfer from '@/view/popup/tabbar-page/nft/transfer.vue'
 import Withdraw from '@/view/popup/withdraw/index.vue'
 import WithdrawInfo from '@/view/popup/withdraw/info.vue'
 import WithdrawConfirm from '@/view/popup/withdraw/confirm.vue'
@@ -120,6 +120,11 @@ const routes = [
         name: 'NFTDetail',
         component: NFTDetail
     },
+    {
+        path: '/NFTTransfer',
+        name: 'NFTTransfer',
+        component: NFTTransfer
+    },
     {
         path: '/currencyDetail',
         name: 'currencyDetail',

+ 6 - 1
src/uilts/chromeExtension.js

@@ -1,4 +1,4 @@
-import { pageUrl } from "@/http/configAPI.js"
+import { pageUrl, websiteUrl } from "@/http/configAPI.js"
 import { guid } from "@/uilts/help";
 
 export const LANDING_PAGE = {
@@ -16,6 +16,11 @@ export const LANDING_PAGE_JUMP_INFO = {
     url: pageUrl
 }
 
+export const WEBSITE_USER_INFO = {
+    name: 'userInfo',
+    url: websiteUrl
+}
+
 export function setChromeStorage(params, callback) {
     try {
         if (callback) {

+ 9 - 0
src/uilts/help.js

@@ -101,6 +101,15 @@ export function getBit(value) {
   }
 }
 
+export function getTargetElementWhenClick(e) { 
+  const { target, path } = e;
+  let result = null;
+  if (Array.isArray(path) && path.length > 0) { 
+    result = path.find((item) => item.denetClickLogkey)
+  }
+  return result
+}
+
 export function getCookie(name) {
   var strcookie = document.cookie; //获取cookie字符串
   var arrcookie = strcookie.split("; "); //分割

+ 114 - 0
src/view/components/nft-card.vue

@@ -0,0 +1,114 @@
+<template>
+    <div class="show" :style="{ zoom: zoom }">
+        <div class="card" :class="item.modelName">
+            <div class="logo">
+                <img v-if="item.logoImagePath" :src="item.logoImagePath" alt="" />
+            </div>
+            <div class="member">{{ item.projectName === '' ? 'xxxx' : item.projectName }}</div>
+            <div class="number">{{ nftItemId === '' ? '0000' : nftItemId }}</div>
+        </div>
+        <img class="bg" :src="item.modelImagePath" />
+    </div>
+</template>
+
+<script setup>
+import { onBeforeMount, defineProps, ref } from 'vue'
+
+const zoom = ref(1);
+
+const props = defineProps({
+    item: {
+        type: Object,
+        default: {},
+    },
+    nftItemId: {
+        type: String,
+        default: '0000',
+    },
+    width: {
+        type: Number,
+        default: 400
+    }
+})
+
+onBeforeMount(() => {
+    if (props.width) {
+        zoom.value = props.width / 400
+    }
+})
+</script>
+
+<style lang='scss' scoped>
+.show {
+    position: relative;
+    overflow: hidden;
+    width: 400px;
+    height: 400px;
+    .card {
+        position: absolute;
+        left: 53px;
+        top: 103px;
+        width: 294px;
+        height: 186px;
+        .logo {
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            width: 100px;
+            height: 100px;
+            border-radius: 50%;
+            background-color: #fff;
+            img {
+                width: 100%;
+                height: 100%;
+                border-radius: 50%;
+                object-fit: cover;
+            }
+        }
+        .member {
+            position: absolute;
+            top: 11px;
+            left: 11px;
+            width: 228px;
+            font-size: 12px;
+            text-align: left;
+            font-weight: 800;
+            line-height: 13px;
+        }
+        .number {
+            position: absolute;
+            top: 11px;
+            right: 10px;
+            font-size: 12px;
+            font-weight: 800;
+            line-height: 13px;
+            letter-spacing: 1px;
+        }
+        &.s1 {
+            .member, .number {
+                color: #ffffff;
+            }
+        }
+        &.s2 {
+            .member, .number {
+                color: #4AC3E1;
+            }
+        }
+        &.s3 {
+            .member, .number {
+                color: #606C94;
+            }
+        }
+        &.s4 {
+            .member, .number {
+                color: #504215;
+            }
+        }
+    }
+    .bg {
+        width: 100%;
+        height: 100%;
+    }
+}
+</style>

+ 29 - 2
src/view/components/popup-transactions.vue

@@ -43,6 +43,18 @@
                                 require('@/assets/svg/icon-list-top-up.svg')
                             " />
                         </template>
+                        <!-- 收入 - 盲盒 -->
+                        <template v-else-if="item.bizType == 7">
+                            <img class="icon-avatar" style="margin-left:-4px" :src="item.bizData.imagePath" v-if="item.bizData && item.bizData.imagePath" />
+                            <img class="icon-avatar" style="margin-left:-4px" :src="require('@/assets/svg/icon-wallter-list-blind-box.svg')" v-else />
+                            <img class="icon-give" :src="require('@/assets/svg/icon-list-withdraw-s.svg')" />
+                        </template>
+                        <!-- 收入 - 盲盒 -->
+                        <template v-else-if="item.bizType == 8">
+                            <img class="icon-avatar" style="margin-left:-4px" :src="item.bizData.imagePath" v-if="item.bizData && item.bizData.imagePath" />
+                            <img class="icon-avatar" style="margin-left:-4px" :src="require('@/assets/svg/icon-wallter-list-blind-box.svg')" v-else />
+                            <img class="icon-give" :src="require('@/assets/svg/icon-get-giveaways-s.svg')" />
+                        </template>
                         <!-- 支出 - 提现 -->
                         <template v-else-if="item.bizType == -1">
                             <img style="margin-left:-4px" :src="
@@ -69,6 +81,12 @@
                                 require('@/assets/svg/icon-list-withdraw-s.svg')
                             " />
                         </template>
+                        <!-- 交易链手续费 -->
+                        <template v-else-if="item.bizType == -5">
+                            <img class="icon-avatar" style="margin-left:-4px" :src="item.bizData.imagePath" v-if="item.bizData && item.bizData.imagePath" />
+                            <img class="icon-avatar" style="margin-left:-4px" :src="require('@/assets/img/icon-box2.png')" v-else />
+                            <img class="icon-give" :src="require('@/assets/svg/icon-transaction-s.svg')" />
+                        </template>
                     </div>
                     <div class="info-wrapper">
                         <div class="left">
@@ -91,6 +109,12 @@
                                 <template v-else-if="item.bizType == 6">
                                     Lottery Refund
                                 </template>
+                                <template v-else-if="item.bizType == 7">
+                                    Sell NFT Mystery box*{{(item.bizData && item.bizData.nftItemCount || '')}}
+                                </template>
+                                <template v-else-if="item.bizType == 8">
+                                    NFT Refund
+                                </template>
                                 <template v-else-if="item.bizType == -1">
                                     Withdrawal
                                 </template>
@@ -98,11 +122,14 @@
                                     Giveaways
                                 </template>
                                 <template v-else-if="item.bizType == -3">
-                                    Mystery box*{{(item.bizData && item.bizData.nftItemCount || '')}}  Sold
+                                    Buy NFT Mystery box*{{(item.bizData && item.bizData.nftItemCount || '')}}
                                 </template>
                                 <template v-else-if="item.bizType == -4">
                                     Lottery Giveaway
                                 </template>
+                                <template v-else-if="item.bizType == -5">
+                                    Transaction Royalties
+                                </template>
                             </div>
                             <div class="time">{{ moment(item.createTimestamp).format('MM-DD HH:mm:ss') }}</div>
                         </div>
@@ -183,7 +210,7 @@
                                         :class="{'balance-direction': item.trxAmountCurrencyInfo.tokenSymbol.length + ('' + item.trxAmountValue).length > 12}">
 
                                         <!--支出—— -2:零钱余额支付 、-3: NFT盲盒余额支付 -->
-                                        <span class="amount" v-if="item.bizType == -2 || item.bizType == -3 || item.bizType == -4">
+                                        <span class="amount" v-if="item.bizType == -2 || item.bizType == -3 || item.bizType == -4 || item.bizType == -5">
                                             <a-tooltip :title="'-' + item.trxAmountValue">
                                                 -{{ getBit(item.trxAmountValue) || 0 }}
                                             </a-tooltip>

+ 29 - 7
src/view/iframe/buy-nft/buy/home.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="dialog">
+    <div class="dialog"  :style="{'height': dialogStyle.height + 'px'}">
         <!-- home -->
         <div class="area-title">
             <img :src="require('@/assets/svg/icon-close.svg')" @click="clickClose" />
@@ -16,8 +16,7 @@
             <!-- 首页 -->
             <div class="mark">
                 <div class="sold">SOLD: {{ state.data.itemSoldCount || 0 }}/{{ state.data.itemTotalCount || 0 }} </div>
-                <div class="limit">Buy Limit: {{ state.data.userBuyCount || 0 }}/{{ state.data.perUserBuyLimit || 0 }}
-                </div>
+                <div class="limit" v-if="showDesc">Buy Limit: {{ state.data.userBuyCount || 0 }}/{{ state.data.perUserBuyLimit || 0 }}</div>
             </div>
             <div class="btn-area">
                 <template v-for="item in state.data.salePlans.splice(0, 2).reverse()">
@@ -81,12 +80,16 @@
 </template>
 <script setup>
 import { useRouter } from 'vue-router'
-import { onMounted, reactive, inject, } from "vue";
+import { onMounted, reactive, inject, ref } from "vue";
 import { getNftMysteryBoxSaleInfo } from "@/http/nft";
 import BtnLoading from '../components/btn-loading.vue'
 import { getQueryString } from "@/uilts/help";
 let pay_info = inject('pay_info');
-const router = useRouter()
+let router = useRouter()
+let showDesc = ref(true)
+let dialogStyle = reactive({
+    height: '800'
+})
 let state = reactive({
     data: {
         salePlans: [
@@ -118,7 +121,19 @@ const clickJump = (item) => {
     pay_info.home.sale_plan = item
     router.push({ path: '/pay' });
 }
+
+const setDialogStyle = () => {
+    let clientHeight = window.innerHeight;
+    if(clientHeight >= 840) {
+        dialogStyle.height = 800;
+    } else {
+        dialogStyle.height = clientHeight - 40;
+    }
+}
+
 onMounted(() => {
+    setDialogStyle();
+
     let nft_project_Id = router.currentRoute.value.query.nftProjectId
     let nft_group_Id = router.currentRoute.value.query.nft_group_Id
     if(nft_group_Id){
@@ -135,6 +150,10 @@ onMounted(() => {
         if (res.code == 0) {
             state.data = res.data
             pay_info.home = res.data
+            let { perUserBuyLimit, itemTotalCount } = res.data;
+            if (perUserBuyLimit && itemTotalCount && perUserBuyLimit >= itemTotalCount) {
+                showDesc.value = false;
+            }
         } else {
 
         }
@@ -151,7 +170,6 @@ onMounted(() => {
     max-width: 1000px;
     min-width: 1000px;
     max-height: 90%;
-    min-height: 800px;
     z-index: 23;
     display: flex;
     flex-direction: column;
@@ -184,7 +202,7 @@ onMounted(() => {
 
         img {
             width: 100%;
-            height: 100%;
+            object-fit: contain;
         }
     }
 
@@ -217,6 +235,7 @@ onMounted(() => {
             display: flex;
             padding: 15px 0;
             min-height: 50px;
+            box-sizing: border-box;
 
             .buy5 {
                 border: 1px solid #1D9BF0;
@@ -233,6 +252,7 @@ onMounted(() => {
                 font-size: 14px;
                 cursor: pointer;
                 margin-right: 12px;
+                box-sizing: border-box;
 
                 .left {
                     margin-right: 20px;
@@ -279,6 +299,8 @@ onMounted(() => {
                 justify-content: space-between;
                 padding: 0 15px 0 20px;
                 margin-right: 25px;
+                box-sizing: border-box;
+                min-height: 50px;
 
                 .left {
                     margin-right: 20px;

+ 14 - 2
src/view/iframe/buy-nft/buy/open-box.vue

@@ -2,9 +2,20 @@
     <!-- gif -->
     <div class="box_content">
         <img :src="require('@/assets/gif/box.gif')" class="box" v-show="state.box.show" />
-        <div class="nft" v-for="item in state.nft.data" v-show="item.show">
+        <div
+            class="nft"
+            :key="index"
+            v-for="(item, index) in state.nft.data"
+            v-show="item.show">
             <div class="detail">
-                <img :src="item.imagePath" alt="" />
+                <img
+                    v-if="item.imagePath"
+                    :src="item.imagePath" />
+                <nft-card
+                    v-else
+                    :nftItemId="item.nftItemId"
+                    :item="item.createImageInfo">
+                </nft-card>
             </div>
             <p>{{ item.nftItemName }}</p>
         </div>
@@ -12,6 +23,7 @@
 </template>
 <script setup>
 import { reactive, onMounted, inject } from 'vue'
+import nftCard from "@/view/components/nft-card.vue"
 import router from "@/router/buy-nft.js";
 let pay_info = inject('pay_info');
 let state = reactive({

+ 16 - 3
src/view/iframe/buy-nft/buy/pay.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="dialog">
+    <div class="dialog" :style="{'height': dialogStyle.height + 'px'}">
         <!-- home -->
         <div class="area-title">
             <img :src="require('@/assets/svg/icon-back.svg')" @click="clickBack" />
@@ -111,6 +111,10 @@ let currentCurrencyInfo = reactive({
     balance: "",
 });
 
+let dialogStyle = reactive({
+    height: '800'
+})
+
 const updateData = (obj_data) => {
     if (Number(obj_data.balance) >= Number(pay_info.home.sale_plan.price)) {
         state.is_btn_grey = false
@@ -196,9 +200,19 @@ const getCurrencyInfo = async () => {
     }
 }
 
+const setDialogStyle = () => {
+    let clientHeight = window.innerHeight;
+    if(clientHeight >= 840) {
+        dialogStyle.height = 800;
+    } else {
+        dialogStyle.height = clientHeight - 40;
+    }
+}
+
 onMounted(() => {
     currentCurrencyInfo.currencyCode = pay_info.home.sale_plan.currencyCode
-    getLocalCurrencyInfoByCode()
+    getLocalCurrencyInfoByCode();
+    setDialogStyle()
 })
 
 
@@ -210,7 +224,6 @@ onMounted(() => {
     max-width: 1000px;
     min-width: 800px;
     max-height: 90%;
-    min-height: 800px;
     z-index: 23;
     display: flex;
     flex-direction: column;

+ 59 - 5
src/view/iframe/nft/card.vue

@@ -2,9 +2,9 @@
     <div class="nft" :class="{ border: isShare }">
         <template v-if="!isLoading">
             <div class="title">
-                <div class="tag">
+                <div class="tag" :class="{ share: !isShare }">
                     <img class="logo" :src="saleData.nftProjectAvatar" />
-                    <font class="text">{{saleData.nftProjectName}}</font>
+                    <font class="text" :class="{ share: !isShare }">{{saleData.nftProjectName}}</font>
                     <img class="tagImg" :src=" require('@/assets/img/icon-nft.png') " />
                 </div>
                 <div class="share" v-if="!isShare" @click="share">
@@ -14,7 +14,16 @@
             <div class="content">
                 <img :src="saleData.windowImagePath" />
             </div>
-            <div class="buy" @click="buy">
+            <div
+                v-if="saleData.purchaseStatus === 0"
+                class="buy disabled">
+                <img class="guide" v-if="isShowGuide" :src=" require('@/assets/img/icon-arrow.png') " />
+                <button>Buy NFT</button>
+            </div>
+            <div
+                v-else
+                class="buy"
+                @click="buy">
                 <img class="guide" v-if="isShowGuide" :src=" require('@/assets/img/icon-arrow.png') " />
                 <button>Buy NFT</button>
             </div>
@@ -23,7 +32,7 @@
 </template>
 
 <script setup>
-import { onBeforeMount, ref } from 'vue'
+import { onBeforeMount, ref, onMounted, onBeforeUnmount } from 'vue'
 import { getTwitterSaleNftProjectInfo, getNftProjectInfo } from '@/http/nft'
 import { pageUrl } from "@/http/configAPI.js"
 import { getChromeStorage, setChromeStorage } from '@/uilts/chromeExtension.js'
@@ -109,6 +118,7 @@ const share = () => {
 const buy = () => {
     getChromeStorage('userInfo', (_userInfo) => {
         if (!_userInfo) {
+            setChromeStorage({ buyNFTCardData: JSON.stringify({ action: 'buy' })});
             chrome.runtime.sendMessage(
                 { actionType: "POPUP_LOGIN", data: "" },
                 (response) => {
@@ -128,6 +138,14 @@ const buy = () => {
     })
 }
 
+const loginSuccessHandler = async () => {
+    let {action = ''} = await getChromeStorage('buyNFTCardData') || {};
+    if(action == 'buy') {
+        chrome.storage.local.remove("buyNFTCardData");
+        buy();
+    }
+} 
+
 onBeforeMount(() => {
     let urlParams = new URL(window.location.href);
     let searchParmas = new URLSearchParams(urlParams.search);
@@ -139,6 +157,28 @@ onBeforeMount(() => {
         getSaleInfo()
     }
 })
+
+const onRuntimeMsg = () => {
+    chrome.runtime.onMessage.addListener(msgListener)
+}
+
+
+const msgListener = (req, sender, sendResponse) => {
+    switch (req.actionType) {
+        case 'BG_LOGIN_SET_USERINFO_CB':
+            loginSuccessHandler();
+            break;
+    }
+}
+
+onMounted(() => {
+    onRuntimeMsg();
+})
+
+
+onBeforeUnmount(() => {
+    chrome.runtime.onMessage.removeListener(msgListener);
+})
 </script>
 
 <style lang='scss'>
@@ -165,8 +205,12 @@ body {
 
         .tag {
             display: flex;
+            max-width: 93%;
             align-items: center;
             padding-left: 15px;
+            &.share {
+                max-width: 84%;
+            }
 
             .logo {
                 overflow: hidden;
@@ -179,7 +223,14 @@ body {
             .text {
                 font-size: 18px;
                 font-weight: bold;
+                max-width: calc(100% - 80px);
                 margin: 0 7px;
+                overflow: hidden;
+                white-space: nowrap;
+                text-overflow: ellipsis;
+                &.share {
+                    max-width: calc(100% - 80px);
+                }
             }
 
             .tagImg {
@@ -190,7 +241,7 @@ body {
 
         .share {
             cursor: pointer;
-            padding-right: 15px;
+            padding-right: 10px;
 
             img {
                 width: 19px;
@@ -213,6 +264,9 @@ body {
         height: 54px;
         display: flex;
         justify-content: center;
+        &.disabled {
+            opacity: .1;
+        }
         .guide {
             position: absolute;
             top: 6px;

+ 2 - 2
src/view/iframe/publish/components/preview-card.vue

@@ -3,7 +3,7 @@
     <div class="wrapper">
         <div class="card-container">
             <!-- 安装之后的卡片样式 -->
-            <div v-if="installStatus" class="left" :style="{'width': reviewCanvasParams.width+ 'px'}">
+            <div v-show="installStatus" class="left" :style="{'width': reviewCanvasParams.width+ 'px'}">
                 <div class="head" :style="{'zoom': reviewCanvasParams.zoom}">
                     <img :src="userInfo.avatarUrl"
                         class="avatar"/>
@@ -40,7 +40,7 @@
 
             <!-- 安装之前的卡片样式 -->
             <div class="content-before"
-                v-else 
+                v-show="!installStatus"
                 :style="{'width': (baseFormData.rewardType === RewardType.money) ? `${reviewCanvasParams.width}px` : '100%'}">
                 <div class="head" 
                     :style="{'zoom': reviewCanvasParams.zoom}">

+ 59 - 2
src/view/iframe/publish/give-dialog.vue

@@ -153,7 +153,7 @@
                                                         :src="require('@/assets/svg/icon-winner-v2.svg')"/>
                                                     Winner Count
                                                 </div>
-                                                <div class="msg" v-show="selectModeInfo.type == PlayType.common">Recommend Winners 100~10000</div>
+                                                <div class="msg" v-show="selectModeInfo.type == PlayType.common">Recommend Winners 50~500</div>
                                             </div>
                                             <input v-model="baseFormData.totalCount"
                                                 placeholder="0"
@@ -176,6 +176,7 @@
                                             </div>
                                         </div>
                                     </div>
+                                    <div class="usd-min-message" v-show="isShowUsdMinMessage" v-html="checkUsdMinNumber('inTemplate')"></div>
                                     <div class="giveaway-poster" @click="customCoverImg">
                                         <div class="show-img">
                                             <div
@@ -510,6 +511,9 @@ let atUserList = ref([]);
 // 表单错误提示
 let iptErrMsgTxt = ref("Select a reward");
 
+// usd最小金额限制提示展示
+let isShowUsdMinMessage = ref(false);
+
 // 是否返回
 let isBack = ref(false);
 
@@ -795,7 +799,7 @@ const setDialogStyle = (resize = false) => {
             dialogStyle.dialogHeight = clientHeight - gapSafe;
         } else {
             if(resize) {
-                dialogStyle.dialogHeight = 680;
+                dialogStyle.dialogHeight = 720;
             }
         }
 
@@ -1014,6 +1018,12 @@ const updateCurrencyBanlce = async () => {
     if(currentCurrencyInfo.value.currencyCode == 'USD') {
         let currencyInfoRes = await getCurrencyByCode({currencyCode: currentCurrencyInfo.value.currencyCode});
 
+        calcRechPayAmount({
+            currencyCode: currentCurrencyInfo.value.currencyCode,
+            orderAmountValue: baseFormData.amountValue,
+            payChannel: 'ach'
+        });
+
         if(currencyInfoRes.code == 0 && currencyInfoRes.data) {
             currentCurrencyInfo.value = currencyInfoRes.data;
         }
@@ -1372,6 +1382,34 @@ const calcIptValue = (cb) => {
     }
 };
 
+/**
+ * usd最小金额判断
+ * luckdropPostConfig是一个列表,需要根据当前的玩法选择对应的Limit信息比对
+ * luckdropPostConfig[i].usdLimitEnable 当前选中的token是否开启usd最小金额判断
+ */
+const checkUsdMinNumber = (isInTemplate) => {
+    let forbiddenText = '';
+    const { usdPrice, luckdropPostConfig = [] } = currentCurrencyInfo.value;
+    let currentLuckDropConfig = luckdropPostConfig.find(item => item.luckdropType === selectModeInfo.type);
+    if (baseFormData.rewardType === RewardType.money && currentLuckDropConfig?.usdLimitEnable === 1) {
+        const { amountValue, totalCount } = baseFormData;
+        if (currentLuckDropConfig?.minTotalUsdAmount === 0 || currentLuckDropConfig?.minAvgUsdAmount === 0) {
+            // 当前token允许的usd最小金额为0 或单个红包最小金额为0,则无限制
+            return forbiddenText;
+        } else {
+            const isAmountForbidden = currentLuckDropConfig?.minTotalUsdAmount ? math.format(math.evaluate(amountValue * usdPrice)) < currentLuckDropConfig.minTotalUsdAmount : false;
+            const isAvgForbidden = currentLuckDropConfig?.minAvgUsdAmount ? math.format(math.evaluate(amountValue / totalCount * usdPrice)) < currentLuckDropConfig.minAvgUsdAmount : false;
+            forbiddenText = isAmountForbidden && isAvgForbidden ? 
+                            `The prize pool must be above 
+                            ${isInTemplate ? ('<span class="font-color-1D9BF0">$' + currentLuckDropConfig.minTotalUsdAmount + '</span>') : ('$' + currentLuckDropConfig.minTotalUsdAmount)} 
+                            or the average prize must be above
+                            ${isInTemplate ? ('<span class="font-color-1D9BF0">$' + currentLuckDropConfig.minAvgUsdAmount +' per person.</span>' ): ('$' + currentLuckDropConfig.minAvgUsdAmount + ' per person.') }`
+                            : '';
+        }
+    }
+    return forbiddenText;
+};
+
 /**
  * 设置输入提示语
  */
@@ -1390,6 +1428,9 @@ const onIptSetErrorTxt = (params = {}) => {
         iptErrMsgTxt.value = "Enter an amount";
     } else if (!baseFormData.totalCount || baseFormData.totalCount == '0') {
             iptErrMsgTxt.value = "Enter the number of winners";
+    } else if (iptErrMsgTxt.value = checkUsdMinNumber()) {
+        // 最小法币金额限制
+        return isShowUsdMinMessage.value = true;
     } else if(baseFormData.rewardType === RewardType.money && +baseFormData.amountValue <= +currentCurrencyInfo.value.balance) {
         // 输入金额 小于 余额
         let res = calcIptValue();
@@ -1941,6 +1982,12 @@ onMounted(() => {
 });
 </script>
 
+<style lang="scss">
+.font-color-1D9BF0 {
+    color: #1D9BF0;
+}
+</style>
+
 <style lang="scss" scoped>
 
 :deep() .ant-switch {
@@ -2373,6 +2420,16 @@ onMounted(() => {
                     }
                 }
 
+                .usd-min-message {
+                    font-style: normal;
+                    font-weight: 400;
+                    font-size: 12px;
+                    line-height: 16px;
+                    letter-spacing: 0.3px;
+                    color: #C88726;
+                    margin-top: 8px;
+                }
+
                 .giveaway-poster {
                     display: flex;
                     align-items: center;

+ 5 - 1
src/view/iframe/publish/tool-box/child/editor.vue

@@ -153,7 +153,11 @@ const searchHandler = async (_params) => {
   }
   
   let convertRes = await convertUrl({ params: { originUrl: siteUrl.value } });
-  let params = { convertUrl: siteUrl.value, originUrl: siteUrl.value, appId: currentApp.appId, linkImagePath: currentApp.linkImagePath, currentApp };
+  let params = { convertUrl: siteUrl.value, 
+                  originUrl: siteUrl.value, 
+                  appId: currentApp.appId, 
+                  linkImagePath: currentApp.linkImagePath, 
+                  currentApp };
 
   loadingHide();
   clearTimeout(timer);

+ 5 - 5
src/view/iframe/publish/tool-box/child/preview.vue

@@ -37,7 +37,7 @@
                     <div class="card-wrapper" :style="{ 'zoom': reviewCanvasParams.zoom }">
                         <img class="cover" v-if="previewData.linkImagePath && previewData.appId"
                             :src="previewData.linkImagePath" />
-                        <iframe class="iframe" :src="previewData.convertUrl" scrolling="no" v-else></iframe>
+                        <iframe class="iframe" sandbox :src="previewData.convertUrl" scrolling="no" v-else></iframe>
 
                         <div class="bottom-bar">
                             <div class="site-url">DeNet.me</div>
@@ -120,7 +120,7 @@ const props = defineProps({
 watch(() => props.screenshotWebsiteData,
     (newVal) => {
         let { appId } = props.previewData;
-        if (loadingHide && !appId && (newVal.url || newVal.status)) {
+        if (loadingHide && (!appId || appId && !props.previewData.linkImagePath ) && (newVal.url || newVal.status)) {
             loadingHide();
             loadingHide = null;
             submitPublish();
@@ -198,7 +198,7 @@ const publishHandler = () => {
         return;
     }
 
-    if (!appId && !props.screenshotWebsiteData.url) {
+    if ((!appId || appId && !props.previewData.linkImagePath) && !props.screenshotWebsiteData.url) {
         loadingHide = message.loading('loading...', 0);
         return;
     }
@@ -398,7 +398,7 @@ onUnmounted(() => {
                     top: 90px;
 
                     .iframe {
-                        height: calc(100% - 73px);
+                        height: calc(100% - 71px);
                         width: 100%;
                         border: none;
                         pointer-events: none;
@@ -408,7 +408,7 @@ onUnmounted(() => {
                     .cover {
                         height: calc(100% - 73px);
                         width: 100%;
-                        object-fit: contain;
+                        object-fit: cover;
                     }
 
                     .bottom-bar {

+ 3 - 3
src/view/iframe/publish/tool-box/index.vue

@@ -64,9 +64,9 @@ const changeShowCom = (params) => {
     previewData.linkImagePath = params.linkImagePath || '';
     previewData.currentApp = params.currentApp || {};
 
-    if(!params.appId) {
-        screenshotWebsiteData.url = '';
-        screenshotWebsiteData.status = '';
+    screenshotWebsiteData.url = '';
+    screenshotWebsiteData.status = '';
+    if(!params.appId || params.appId && !params.linkImagePath) {
         screenshotWebsite({
             params: {
                 url: params.convertUrl

+ 1 - 1
src/view/iframe/tool-box/card.vue

@@ -8,7 +8,7 @@
             </div>
         </div>
         <div class="content" v-if="pre_view">
-            <iframe :src="iframe_url" frameborder="0"></iframe>
+            <iframe :src="iframe_url" frameborder="0" sandbox></iframe>
         </div>
         <div class="content" v-else>
             <iframe :src="state.iframe_url" v-show="state.status == 'iframe'" ref="dom_iframe" frameborder="0"

+ 0 - 1
src/view/popup/components/tabbar.vue

@@ -160,7 +160,6 @@ const onMessage = () => {
 }
 
 const msgListener = (req, sender, sendResponse) => {
-    ;
     switch (req.actionType) {
         case 'CONTENT_POPUP_PAGE_SHOW':
             init();

+ 29 - 3
src/view/popup/currency-detail.vue

@@ -7,6 +7,7 @@
             :transactionsRouterParams="{
               backUrl: 'back'
             }"
+            back_url="/"
             @on-refresh="onRefresh" />
     <div class="top">
       <img
@@ -71,7 +72,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, inject, reactive } from "vue";
+import { ref, onMounted, inject, reactive, onBeforeUnmount } from "vue";
 import router from "@/router/popup.js";
 import Report from "@/log-center/log";
 import { getStorage } from "@/uilts/help";
@@ -261,7 +262,6 @@ const showSendGiveawayDialog = (params = {}) => {
       showCurrencySelect.value = true;
       currencyOpertionType = "SEND";
   } else {
-    console.log(params,'params')
       setLocalSelectCurrencyInfo(params)
       setTimeout(() => {
         chrome.runtime.sendMessage({ 
@@ -294,6 +294,12 @@ const confirmDeposit = (params) => {
   };
   let guideUrl = chrome.runtime.getURL('/iframe/ach-cashier.html');
   setChromeStorage({ achPayInfo : JSON.stringify(achPayInfo)});
+  let str = window.location.hash + '&refresh=true';
+  let path = str.substring(1, str.length);
+  setChromeStorage({ achPayData : JSON.stringify({
+    form: 'popupPage',
+    path
+  })});
 
   chrome.tabs.create({
     url: guideUrl
@@ -325,13 +331,28 @@ const onDepositAmountInput = async (params = {}) => {
   }
 }
 
+
+const onMessage = () => {
+    chrome.runtime.onMessage.addListener(msgListener)
+}
+
+const msgListener = (req, sender, sendResponse) => {
+    switch (req.actionType) {
+        case 'CONTENT_POPUP_PAGE_SHOW':
+            let {refresh = false} = router.currentRoute.value.query;
+            if(refresh && currencyInfo.value.tokenSymbol) {
+              onRefresh();
+            }
+            break;
+    }
+}
+
 onMounted(() => {
     let {params = '{}'} = router.currentRoute.value.query;
 
     let {currencies = [], totalBalance = 0, totalUsdEstimateBalance = 0} =  JSON.parse(params);
 
     currenciesData.value = currencies;
-
     if(currencies.length) {
       currencyInfo.value = {
         ...currencies[0],
@@ -348,6 +369,11 @@ onMounted(() => {
     } else {
       showSendBtn.value = true;
     }
+    onMessage();
+})
+
+onBeforeUnmount(() => {
+    chrome.runtime.onMessage.removeListener(msgListener);
 })
 
 </script>

+ 3 - 1
src/view/popup/setting/index.vue

@@ -11,7 +11,7 @@
 
         <div class="item">
             <div class="l">Announcement Notification</div>
-            <div class="r">
+            <div class="r" v-if="noticeShow">
                 <a-switch v-model:checked="noticeStatus" @change="change"></a-switch>
             </div>
         </div>
@@ -24,6 +24,7 @@ import router from "@/router/popup.js";
 import { getSetting, putSetting } from "@/http/user";
 
 let noticeStatus = ref(true);
+let noticeShow = ref(false);
 
 function back() {
     router.back();
@@ -65,6 +66,7 @@ onBeforeMount(() => {
         if (code === 0) {
             noticeStatus.value = data.noticeSwitch === 1 ? true : false;
         }
+        noticeShow.value = true;
     });
 });
 </script>

+ 0 - 1
src/view/popup/tabbar-page/index.vue

@@ -111,7 +111,6 @@ const onRuntimeMsg = () => {
 }
 
 const msgListener = (req, sender, sendResponse) => {
-  ;
   switch (req.actionType) {
     case 'BG_LOGIN_SET_USERINFO_CB':
       if (!userInfo.value.accessToken) {

+ 25 - 3
src/view/popup/tabbar-page/message/index.vue

@@ -15,10 +15,24 @@
                   <img class="icon-give" :src="require('@/assets/svg/icon-get-giveaways-s.svg')" />
                 </template>
                 <!-- 发出去红包 -->
-                <template v-else-if="2">
+                <template v-else-if="item.type == 2">
                   <img class="icon-big-give" :src="require('@/assets/svg/icon-send-giveaways-s.svg')" />
                   <img class="icon-mark-give" :src="require('@/assets/svg/icon-send-giveaways-mark.svg')" />
                 </template>
+                <!-- 转出NFT记录 -->
+                <template v-else-if="item.type == 4">
+                  <img
+                    v-if="item.nftItemVO?.imagePath"
+                    class="icon-big-give"
+                    :src="item.nftItemVO?.imagePath" />
+                  <div v-else style="margin-top: 12px;">
+                    <nft-card
+                      :nftItemId="item.nftItemId"
+                      :item="item.nftItemVO.createImageInfo"
+                      :width="34">
+                    </nft-card>
+                  </div>
+                </template>
               </div>
               <div class="info-wrapper" :class="{ 'info-center': item.type == 1 }">
                 <div class="left">
@@ -32,6 +46,9 @@
                     <template v-else-if="item.type == 3">
                       Lottery
                     </template>
+                    <template v-else-if="item.type == 4">
+                      Transfer NFT
+                    </template>
                   </div>
                   <div class="time">
                     {{ moment(item.timestamp).format("MM-DD HH:mm:ss") }}
@@ -139,6 +156,11 @@
                           Giveaway Expired
                         </template>
                       </template>
+                      <template v-else-if="item.type == 4">
+                        <template v-if="item.status == 0 || item.status == 1">Transferring</template>
+                        <template v-else-if="item.status == 2">Successful</template>
+                        <template v-else-if="item.status == 3">Transfe Failed</template>
+                      </template>
                     </div>
                     <!-- 发出的红包显示 -->
                     <div class="desc" v-if="item.type == 2">
@@ -208,7 +230,7 @@
                     </div>
                   </div>
                   <!-- 发红包—— 未发出、进行中 隐藏 -->
-                  <img v-if="item.type != 2" class="icon" :src="require('@/assets/svg/icon-cell-arrow-right.svg')" />
+                  <img v-if="item.type != 2 && item.type != 4" class="icon" :src="require('@/assets/svg/icon-cell-arrow-right.svg')" />
                 </div>
               </div>
             </div>
@@ -229,6 +251,7 @@ import { ref, onMounted, inject, onBeforeUnmount } from "vue";
 
 import modal from "@/view/popup/components/modal.vue";
 import redDot from "@/view/components/red-dot.vue";
+import nftCard from '@/view/components/nft-card.vue'
 
 import { getBit, formatSecondsAsDaysOrTime } from "@/uilts/help";
 import { getMineLuckdropRecords } from "@/http/account";
@@ -481,7 +504,6 @@ const onMessage = () => {
 }
 
 const msgListener = (req, sender, sendResponse) => {
-  ;
   switch (req.actionType) {
     case 'CONTENT_POPUP_PAGE_SHOW':
       init();

+ 73 - 24
src/view/popup/tabbar-page/more/index.vue

@@ -1,58 +1,101 @@
 <template>
-  <div class="more-page">
-    <div class="more-list">
-      <div
-        class="cell"
-        v-for="(item, index) in moreTabList"
-        :key="index"
-        @click="moreItemHandle(item)"
-      >
-        <img class="icon" :src="item.icon" />
-        <div class="info-wrapper">
-          <div class="left">
-            {{ item.label }}
-          </div>
-          <div class="right">
-            <img
-              class="icon"
-              :src="require('@/assets/svg/icon-cell-arrow-right.svg')"
-            />
-          </div>
+    <div class="more-page">
+        <div class="more-list">
+            <template
+                :key="index"
+                v-for="(item, index) in moreTabList">
+                <template v-if="item.icon">
+                    <div class="cell" @click="moreItemHandle(item)">
+                        <img class="icon" :src="item.icon" />
+                        <div class="info-wrapper">
+                            <div class="left">
+                                {{ item.label }}
+                            </div>
+                            <div class="right">
+                                <img class="icon" :src="require('@/assets/svg/icon-cell-arrow-right.svg')" />
+                            </div>
+                        </div>
+                    </div>
+                </template>
+                <template v-else>
+                    <div class="clear"></div>
+                </template>
+            </template>
         </div>
-      </div>
     </div>
-  </div>
 </template>
 
 <script setup>
-import { ref } from "vue";
+import Report from "@/log-center/log"
+import { ref, onMounted } from "vue";
+import { websiteUrl } from '@/http/configAPI'
+import { getChromeStorage } from '@/uilts/chromeExtension.js'
 
+let userStorage = ref({})
 let moreTabList = ref([
   {
     icon: require("@/assets/svg/icon-website.svg"),
     label: "Official Website",
     href: "https://www.denet.me",
+    type: 'link'
   },
   {
     icon: require("@/assets/svg/icon-twitter.svg"),
     label: "Twitter",
     href: "https://twitter.com/denet2022",
+    type: 'link'
   },
   // {
   //   icon: require("@/assets/svg/icon-discord.svg"),
   //   label: "Discord",
   //   href: "https://discord.gg/wZSz9p8ddG",
+  //   type: 'link'
   // },
   {
       icon: require("@/assets/svg/icon-telegram.svg"),
       label: "Telegram",
-      href: 'https://t.me/denetpro'
+      href: 'https://t.me/denetpro',
+      type: 'link'
+  },
+  {},
+  {
+      icon: require("@/assets/svg/icon-create-nfts.svg"),
+      label: "Create NFTs",
+      type: 'jumpWebsite'
   }
 ]);
 
 const moreItemHandle = (params) => {
-  window.open(params.href);
+    switch (params.type) {
+        case 'link':
+            window.open(params.href);
+            break;
+        case 'jumpWebsite':
+            let url = websiteUrl + `/nft/list?params=${btoa(JSON.stringify(userStorage.value))}`
+            window.open(url);
+            // report
+            Report.reportLog({
+                pageSource: Report.pageSource.denetMorePage,
+                businessType: Report.businessType.buttonClick,
+                objectType: Report.objectType.create_nfts_button,
+            });
+            break;
+    }
 };
+
+const getUserInfo = async () => {
+    userStorage.value = await getChromeStorage('userInfo') || {}
+}
+
+onMounted(() => {
+    getUserInfo()
+    // report
+    Report.reportLog({
+        pageSource: Report.pageSource.denetMorePage,
+        businessType: Report.businessType.pageView,
+    });
+})
+
 </script>
 
 <style scoped lang="scss">
@@ -112,4 +155,10 @@ const moreItemHandle = (params) => {
     }
   }
 }
+
+.clear {
+    overflow: hidden;
+    height: 10px;
+    background-color: #f6f6f6;
+}
 </style>

+ 45 - 80
src/view/popup/tabbar-page/nft/detail.vue

@@ -14,7 +14,14 @@
                     class="img"
                     :src="NFTInfo.imagePath"
                     @click="clickNFTImg"
+                    v-if="NFTInfo.imagePath"
                 />
+                <nft-card
+                    :nftItemId="NFTInfo.nftItemId"
+                    :item="NFTInfo.createImageInfo"
+                    :width="343"
+                    v-else>
+                </nft-card>
             </div>
             <div class="desc item" v-if="nftMetaData.description">
                 <div class="title">Description</div>
@@ -96,23 +103,9 @@
                 </div>
         </div>
         <div class="bottom-bar">
-            <div class="default">NFT Sale function, coming soon</div>
-            <!-- <div class="sell">
-                    <div class="sell-btn">
-                        Sell
-                    </div>
-                </div> 
-                <div class="cancel-sale">
-                    <div class="left">
-                        233 USDT
-                        <div class="final">
-                            (Final 203.5 USDT)
-                        </div>
-                    </div>
-                    <div class="cancel-btn">
-                        Cancel sale
-                    </div>
-                </div> -->
+            <div class="sale" @click="transfer">
+                <span>Transfer</span>
+            </div>
         </div>
     </div>
 </template>
@@ -120,9 +113,10 @@
 <script setup>
 import { ref, onMounted } from "vue";
 import router from "@/router/popup.js";
-
+import nftCard from "@/view/components/nft-card.vue"
 import {getNFTDetail} from "@/http/nft.js";
 
+let timer = ref(null);
 let nftMetaData = ref({});
 let nftDetailData = ref({});
 
@@ -170,6 +164,28 @@ const getDetail = () => {
     })
 }
 
+const transfer = () => {
+    if (Object.keys(nftDetailData.value).length) {
+        clearTimeout(timer.value);
+        router.push({
+            name: 'NFTTransfer',
+            query: {
+                params: JSON.stringify({
+                    nftItemId: nftDetailData.value?.nftItemId,
+                    chainInfo: nftDetailData.value?.chainInfo,
+                    transferFeeCurrencyInfo: nftDetailData.value?.transferFeeCurrencyInfo,
+                    transferFeeAmountValue: nftDetailData.value?.transferFeeAmountValue,
+                })
+            }
+        })
+    } else {
+        clearTimeout(timer.value);
+        timer.value = setTimeout(() => {
+            transfer()
+        }, 300)
+    }
+}
+
 onMounted(() => {
     let {params = '{}'} = router.currentRoute.value.query;
     NFTInfo.value = JSON.parse(params);
@@ -352,73 +368,22 @@ onMounted(() => {
         background: #ffffff;
         box-shadow: inset 0px 1px 0px #ececec;
         height: 70px;
-        padding: 15px 16px;
+        padding: 0 16px;
         box-sizing: border-box;
         display: flex;
         align-items: center;
-        justify-content: center;
-
-        .default {
-            font-weight: 500;
-            font-size: 16px;
-            color: #a8a8a8;
-            text-align: center;
-        }
-
-        .sell {
-            width: 100%;
-            height: 100%;
-
-            .sell-btn {
-                width: 120px;
-                height: 40px;
-                box-sizing: border-box;
-                border: 1px solid #e9e9e9;
-                border-radius: 100px;
-                font-weight: 500;
-                font-size: 16px;
-                color: #1d9bf0;
-                display: flex;
-                align-items: center;
-                justify-content: center;
-                position: absolute;
-                right: 16px;
-                cursor: pointer;
-            }
-        }
-
-        .cancel-sale {
-            width: 100%;
-            height: 100%;
+        justify-content: right;
+        .sale {
             display: flex;
             align-items: center;
-            justify-content: space-between;
-
-            .left {
-                font-weight: 500;
-                font-size: 15px;
-                .final {
-                    font-weight: 500;
-                    font-size: 12px;
-                    color: #929292;
-                    margin-top: 6px;
-                }
-            }
-
-            .cancel-btn {
-                width: 120px;
-                height: 40px;
-                box-sizing: border-box;
-                border: 1px solid #e9e9e9;
-                border-radius: 100px;
-                font-weight: 500;
-                font-size: 16px;
-                color: #ff0000;
-                display: flex;
-                align-items: center;
-                justify-content: center;
-                cursor: pointer;
-            }
+            justify-content: center;
+            cursor: pointer;
+            width: 97px;
+            height: 37px;
+            font-size: 14px;
+            color: #1D9BF0;
+            border-radius: 20px;
+            border: 1px solid #1D9BF0;
         }
     }
 }

+ 3 - 2
src/view/popup/tabbar-page/nft/index.vue

@@ -2,7 +2,8 @@
   <div class="nft-page-wrapper" ref="pageWrapperDom" @scroll="pageScroll">
     <div class="content" ref="pageListDom">
       <div class="item" v-for="(item, index) in listData" :key="index" @click="clickNFT(item)">
-        <img :src="item.imagePath" class="img">
+        <img :src="item.imagePath" class="img" v-if="item.imagePath" />
+        <nft-card :nftItemId="item.nftItemId" :item="item.createImageInfo" :width="103" v-else></nft-card>
         <div class="name">{{ item.nftItemName }}</div>
       </div>
     </div>
@@ -20,6 +21,7 @@ import router from "@/router/popup.js";
 
 import { nftListMine } from "@/http/nft.js";
 
+import nftCard from "@/view/components/nft-card.vue"
 import joinGroupFinishDialog from "@/view/components/join-group-finish-dialog.vue";
 
 let listData = ref([]);
@@ -84,7 +86,6 @@ const onMessage = () => {
 }
 
 const msgListener = (req, sender, sendResponse) => {
-  ;
   switch (req.actionType) {
     case 'CONTENT_POPUP_PAGE_SHOW':
       getNFTListMine();

+ 300 - 0
src/view/popup/tabbar-page/nft/transfer.vue

@@ -0,0 +1,300 @@
+<template>
+    <div class="info">
+        <v-head
+            :title="'Transfer'"
+            :show_more="true"
+            :transactionsRouterParams="{
+                backUrl: 'back'
+            }">
+        </v-head>
+        <template v-if="!isSuccess">
+            <div class="content">
+                <div class="token">
+                    <div class="title">Network</div>
+                    <div class="box">
+                        <img :src="transChainInfo?.iconPath" alt="" />
+                        <span>{{ transChainInfo?.chainName }}</span>
+                    </div>
+                </div>
+                <div class="token">
+                    <div class="title">Address</div>
+                    <div class="box">
+                        <input type="text" v-model="address" placeholder="Click to enter" />
+                    </div>
+                </div>
+            </div>
+            <div class="footer">
+                <div class="left">
+                    <div class="txt">Network fee</div>
+                    <span class="money"><a-tooltip :title="feeAmountValue || 0" >{{getBit(feeAmountValue || 0)}}</a-tooltip> {{ feeCurrencyInfo?.tokenSymbol }}</span>
+                    <div class="tips" v-if="showTips">Insufficient balance</div>
+                </div>
+                <div class="right">
+                    <div class="btn enter" @click="next" v-if="isNext">Confirm</div>
+                    <div class="btn" v-else>Confirm</div>
+                </div>
+            </div>
+        </template>
+        <template v-else>
+            <div class="withdraw-status">
+                <img :src="require('@/assets/svg/icon-withdraw-status.svg')" alt="" />
+                <div>
+                    <div class="title">Submitted successfully</div>
+                    <div class="desc">
+                        Please check the status at the message tab
+                    </div>
+                </div>
+            </div>
+            <div class="confirm-btn" @click="doneHandle">Done</div>
+        </template>
+    </div>
+</template>
+
+<script setup>
+import Report from "@/log-center/log"
+import { ref, onMounted, watchEffect } from 'vue'
+import { message } from 'ant-design-vue';
+import { getCurrencyInfoByCode } from '@/http/publishApi'
+import { transferRequest } from '@/http/nft'
+import router from "@/router/popup.js";
+import VHead from '@/view/popup/components/head.vue'
+import Zoom from '@/view/components/component-zoom.vue'
+import { getBit } from "@/uilts/help";
+
+const isNext = ref(false)
+const isSuccess = ref(false)
+const isPayment = ref(false)
+const showTips = ref(false)
+const transChainInfo = ref({})
+const feeAmountValue = ref(0)
+const feeCurrencyInfo = ref({})
+const address = ref('')
+const nftId = ref('')
+
+const getCurrentyInfo = (data) => {
+    getCurrencyInfoByCode({
+        params: {
+            currencyCode: data?.currencyCode
+        }
+    }).then(res => {
+        let { code, data } = res;
+        if (code === 0) {
+            isPayment.value = Number(data?.balance) >= Number(feeAmountValue.value)
+            showTips.value = Number(data?.balance) < Number(feeAmountValue.value)
+        }
+    })
+}
+
+const next = () => {
+    transferRequest({
+        params: {
+            nftItemId: nftId.value,
+            receiveAddress: address.value
+        }
+    }).then(res => {
+        let { code } = res;
+        let transfer;
+        if (code === 0) {
+            isSuccess.value = true;
+            transfer = 'success'
+        } else if (code === 5302) {
+            transfer = 'fail'
+            message.error(`NFT transfer is under system maintenance, try again in two or three hours.`);
+        } else {
+            transfer = 'fail'
+            message.error(`Transfer failed, please try again`);
+        }
+        // report
+        Report.reportLog({
+            pageSource: Report.pageSource.denetNftTransferPage,
+            businessType: Report.businessType.buttonClick,
+            objectType: Report.objectType.confirm_transfer_button,
+        }, {
+            transfer: transfer
+        });
+    })
+}
+
+const doneHandle = () => {
+    router.push({ name: 'NFT' })
+}
+
+watchEffect(() => {
+    isNext.value = address.value !== '' && isPayment.value
+})
+
+onMounted(() => {
+    let { params = '{}' } = router.currentRoute.value.query;
+    let { chainInfo, nftItemId, transferFeeAmountValue, transferFeeCurrencyInfo } = JSON.parse(params);
+    // set
+    nftId.value = nftItemId;
+    transChainInfo.value = chainInfo
+    feeAmountValue.value = transferFeeAmountValue
+    feeCurrencyInfo.value = transferFeeCurrencyInfo
+
+    getCurrentyInfo(feeCurrencyInfo.value)
+
+    // report
+    Report.reportLog({
+        pageSource: Report.pageSource.denetNftTransferPage,
+        businessType: Report.businessType.pageView,
+    });
+})
+</script>
+
+<style lang="scss" scoped>
+.info {
+    position: relative;
+    height: 100%;
+    .content {
+        height: calc(100% - 48px - 80px);
+        overflow: auto;
+        padding: 13px 16px 0 13px;
+        .token {
+            margin-bottom: 20px;
+            .title {
+                font-weight: 500;
+                font-size: 12px;
+                margin-bottom: 6px;
+                color: #8B8B8B;
+            }
+            .box {
+                border: 1px solid #DBDBDB;
+                border-radius: 8px;
+                height: 44px;
+                display: flex;
+                align-items: center;
+                padding: 0 15px 0 10px;
+                display: flex;
+                flex-wrap: nowrap;
+                justify-content: space-between;
+                img {
+                    width: 20px;
+                    height: 20px;
+                }
+                .up {
+                    width: 13px;
+                    height: 12px;
+                    cursor: pointer;
+                }
+                input {
+                    outline: none;
+                    border: 0;
+                    flex: 1;
+                    height: 18px;
+                    padding: 0 6px;
+                    font-weight: 500;
+                    font-size: 15px;
+                    &::placeholder {
+                        color: #B8B8B8;
+                    }
+                }
+                input::-webkit-outer-spin-button,
+                input::-webkit-inner-spin-button {
+                    -webkit-appearance: none;
+                }
+                input[type='number'] {
+                    -moz-appearance: textfield;
+                }
+                span {
+                    flex: 1;
+                    margin-left: 6px;
+                    font-size: 14px;
+                    font-weight: 500;
+                }
+            }
+        }
+    }
+    .footer {
+        z-index: 11;
+        background: #fff;
+        border-top: 1px solid #DBDBDB;
+        bottom: 0;
+        height: 80px;
+        display: flex;
+        position: absolute;
+        justify-content: space-between;
+        width: 100%;
+        bottom: 0;
+        align-items: center;
+        .left {
+            margin-left: 16px;
+
+            .txt {
+                color: #9D9D9D;
+                font-weight: 400;
+                font-size: 12px;
+            }
+
+            .money {
+                color: #000000;
+                margin-right: auto;
+                font-size: 15px;
+                font-weight: bold;
+            }
+
+            .tips {
+                color: #FF0000;
+                font-weight: 500;
+                font-size: 12px;
+            }
+        }
+
+        .right {
+            margin-right: 16px;
+            .btn {
+                cursor: pointer;
+                width: 140px;
+                height: 46px;
+                line-height: 46px;
+                text-align: center;
+                font-weight: 600;
+                font-size: 18px;
+                color: #FFFFFF;
+                background: #D2D2D2;
+                border-radius: 100px;
+            }
+            .enter {
+                background: #1D9BF0;
+            }
+        }
+    }
+}
+
+.withdraw-status {
+    text-align: center;
+    img {
+        margin-top: 40px;
+        margin-bottom: 34px;
+    }
+    .title {
+        font-weight: 500;
+        font-size: 20px;
+        margin-bottom: 10px;
+    }
+    .desc {
+        font-size: 15px;
+        color: rgba($color: #000000, $alpha: 0.5);
+    }
+}
+
+.confirm-btn {
+    width: 335px;
+    height: 60px;
+    text-align: center;
+    line-height: 60px;
+    border-radius: 100px;
+    background: #1D9BF0;
+    font-weight: 600;
+    font-size: 18px;
+    color: #fff;
+    position: absolute;
+    left: 50%;
+    bottom: 35px;
+    transform: translateX(-50%);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+}
+</style>

+ 0 - 1
src/view/popup/tabbar-page/wallter/popup.vue

@@ -204,7 +204,6 @@ const onMessage = () => {
 }
 
 const msgListener = (req, sender, sendResponse) => {
-    ;
     switch (req.actionType) {
         case 'CONTENT_POPUP_PAGE_SHOW':
             init();

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff