Implement about tab on collectible page (#18269)
* add basics * finalize component * fix lint issues * move color to props * move variants to props * change file structure * working * finalize loader * fix lint issues * fix style issues * add tabs structure * add basics * draft codes * draft * make codes work after rebase * fix lint issues * remove Permissions tab * revert codes * finalize code * fix lint issues * revert podfile.lock * create new reg-sub for traits and chain-id * add real title and description for about tab * resolve comments * fix overview tab * add tests * resolve comments --------- Co-authored-by: Jamie Caprani <jamiecaprani@gmail.com>
This commit is contained in:
parent
433be1daef
commit
da03989c88
|
@ -8,7 +8,7 @@
|
|||
[react-native.linear-gradient :as linear-gradient]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [address theme on-press icon title customization-color]}]
|
||||
[{:keys [address theme on-press icon title customization-color container-style]}]
|
||||
[rn/pressable
|
||||
{:accessibility-label :link-card
|
||||
:on-press on-press}
|
||||
|
@ -17,7 +17,7 @@
|
|||
(properties/gradient-end-color theme customization-color)]
|
||||
:start {:x 0 :y 1}
|
||||
:end {:x 1 :y 1}
|
||||
:style (style/container theme)}
|
||||
:style (merge (style/container theme) container-style)}
|
||||
[rn/view {:style style/icon-container}
|
||||
[social/view
|
||||
{:accessibility-label :social-icon
|
||||
|
|
|
@ -43,29 +43,3 @@
|
|||
(def opensea-button
|
||||
{:flex 1
|
||||
:margin-left 6})
|
||||
|
||||
(def info-container
|
||||
{:flex-direction :row
|
||||
:margin-horizontal 20
|
||||
:margin-top 8
|
||||
:margin-bottom 12})
|
||||
|
||||
(def account
|
||||
{:margin-right 6
|
||||
:flex 1})
|
||||
|
||||
(def network
|
||||
{:margin-left 6
|
||||
:flex 1})
|
||||
|
||||
(def traits-title-container
|
||||
{:margin-left 20
|
||||
:margin-top 8})
|
||||
|
||||
(def traits-item
|
||||
{:margin 6
|
||||
:flex 1})
|
||||
|
||||
(def traits-container
|
||||
{:margin-horizontal 14
|
||||
:margin-vertical 12})
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
(ns status-im.contexts.wallet.collectible.tabs.about.style)
|
||||
|
||||
(def title
|
||||
{:padding-horizontal 20
|
||||
:padding-top 8
|
||||
:padding-bottom 4})
|
||||
|
||||
(def description
|
||||
{:padding-horizontal 20
|
||||
:padding-top 4
|
||||
:padding-bottom 12})
|
||||
|
||||
(def section-label
|
||||
{:margin-horizontal 20
|
||||
:margin-top 12})
|
||||
|
||||
(def link-cards-container
|
||||
{:margin-horizontal 20
|
||||
:margin-top 12
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:flex-wrap :wrap})
|
||||
|
||||
(defn link-card
|
||||
[item-width]
|
||||
{:margin-bottom 16
|
||||
:width item-width})
|
|
@ -0,0 +1,36 @@
|
|||
(ns status-im.contexts.wallet.collectible.tabs.about.view
|
||||
(:require [quo.core :as quo]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.collectible.tabs.about.style :as style]
|
||||
[status-im.contexts.wallet.temp :as temp]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def ^:private link-card-space 28)
|
||||
|
||||
(defn- view-internal
|
||||
[]
|
||||
(let [window-width (rf/sub [:dimensions/window-width])
|
||||
item-width (- (/ window-width 2) link-card-space)
|
||||
{:keys [collectible-data]} (rf/sub [:wallet/last-collectible-details])
|
||||
link-card-container-style (style/link-card item-width)]
|
||||
[:<>
|
||||
[rn/view {:style style/title}
|
||||
[quo/text
|
||||
{:size :heading-2
|
||||
:weight :semi-bold}
|
||||
(:name collectible-data)]]
|
||||
[rn/view {:style style/description}
|
||||
[quo/text
|
||||
{:size :paragraph-2}
|
||||
(:description collectible-data)]]
|
||||
[quo/section-label
|
||||
{:container-style style/section-label
|
||||
:section (i18n/label :t/on-the-web)}]
|
||||
[rn/view {:style style/link-cards-container}
|
||||
(for [item (:cards temp/collectible-about)]
|
||||
^{:key (:title item)}
|
||||
[quo/link-card (assoc item :container-style link-card-container-style)])]]))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
|
@ -0,0 +1,17 @@
|
|||
(ns status-im.contexts.wallet.collectible.tabs.activity.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.temp :as temp]))
|
||||
|
||||
(defn activity-item
|
||||
[item]
|
||||
[:<>
|
||||
[quo/divider-date (:timestamp item)]
|
||||
[quo/wallet-activity item]])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[rn/flat-list
|
||||
{:data temp/collectible-activities
|
||||
:style {:flex 1}
|
||||
:render-fn activity-item}])
|
|
@ -0,0 +1,27 @@
|
|||
(ns status-im.contexts.wallet.collectible.tabs.overview.style)
|
||||
|
||||
(def info-container
|
||||
{:flex-direction :row
|
||||
:margin-horizontal 20
|
||||
:margin-top 8
|
||||
:margin-bottom 12})
|
||||
|
||||
(def account
|
||||
{:margin-right 6
|
||||
:flex 1})
|
||||
|
||||
(def network
|
||||
{:margin-left 6
|
||||
:flex 1})
|
||||
|
||||
(def traits-title-container
|
||||
{:margin-left 20
|
||||
:margin-top 8})
|
||||
|
||||
(def traits-item
|
||||
{:margin 6
|
||||
:flex 1})
|
||||
|
||||
(def traits-container
|
||||
{:margin-horizontal 14
|
||||
:margin-vertical 12})
|
|
@ -0,0 +1,72 @@
|
|||
(ns status-im.contexts.wallet.collectible.tabs.overview.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.resources :as quo.resources]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.collectible.tabs.overview.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- trait-item
|
||||
[{:keys [trait-type value]}]
|
||||
[quo/data-item
|
||||
{:subtitle-type :default
|
||||
:card? true
|
||||
:status :default
|
||||
:size :default
|
||||
:title trait-type
|
||||
:subtitle value
|
||||
:container-style style/traits-item}])
|
||||
|
||||
(defn- traits-section
|
||||
[]
|
||||
(let [traits (rf/sub [:wallet/last-collectible-details-traits])]
|
||||
(when (pos? (count traits))
|
||||
[rn/view
|
||||
[quo/section-label
|
||||
{:section (i18n/label :t/traits)
|
||||
:container-style style/traits-title-container}]
|
||||
[rn/flat-list
|
||||
{:render-fn trait-item
|
||||
:data traits
|
||||
:key :collectibles-list
|
||||
:key-fn :id
|
||||
:num-columns 2
|
||||
:content-container-style style/traits-container}]])))
|
||||
|
||||
(defn- info
|
||||
[]
|
||||
(let [chain-id (rf/sub [:wallet/last-collectible-details-chain-id])
|
||||
{:keys [network-name]} (rf/sub [:wallet/network-details-by-chain-id chain-id])
|
||||
subtitle (string/capitalize (name (or network-name "")))
|
||||
{:keys [name emoji color]} (rf/sub [:wallet/last-collectible-details-owner])]
|
||||
[rn/view {:style style/info-container}
|
||||
[rn/view {:style style/account}
|
||||
[quo/data-item
|
||||
{:card? true
|
||||
:status :default
|
||||
:size :default
|
||||
:title (i18n/label :t/account-title)
|
||||
:subtitle name
|
||||
:emoji emoji
|
||||
:subtitle-type :account
|
||||
:customization-color color}]]
|
||||
[rn/view {:style style/network}
|
||||
[quo/data-item
|
||||
{:subtitle-type :network
|
||||
:card? true
|
||||
:status :default
|
||||
:size :default
|
||||
:title (i18n/label :t/network)
|
||||
:network-image (quo.resources/get-network network-name)
|
||||
:subtitle subtitle}]]]))
|
||||
|
||||
(defn- view-internal
|
||||
[]
|
||||
[:<>
|
||||
[info]
|
||||
[traits-section]])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
|
@ -0,0 +1,15 @@
|
|||
(ns status-im.contexts.wallet.collectible.tabs.view
|
||||
(:require [quo.theme]
|
||||
[status-im.contexts.wallet.collectible.tabs.about.view :as about]
|
||||
[status-im.contexts.wallet.collectible.tabs.activity.view :as activity]
|
||||
[status-im.contexts.wallet.collectible.tabs.overview.view :as overview]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [selected-tab]}]
|
||||
(case selected-tab
|
||||
:overview [overview/view]
|
||||
:about [about/view]
|
||||
:activity [activity/view]
|
||||
nil))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
|
@ -1,14 +1,12 @@
|
|||
(ns status-im.contexts.wallet.collectible.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.resources :as quo.resources]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.scroll-page.view :as scroll-page]
|
||||
[status-im.contexts.wallet.collectible.style :as style]
|
||||
[status-im.contexts.wallet.temp :as temp]
|
||||
[status-im.contexts.wallet.collectible.tabs.view :as tabs]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
@ -42,105 +40,17 @@
|
|||
:icon-left :i/opensea}
|
||||
(i18n/label :t/opensea)]])
|
||||
|
||||
(def activity-tabs-data
|
||||
(def tabs-data
|
||||
[{:id :overview
|
||||
:label (i18n/label :t/overview)
|
||||
:accessibility-label :overview-tab}
|
||||
{:id :activity
|
||||
:label (i18n/label :t/activity)
|
||||
:accessibility-label :activity-tab}
|
||||
{:id :permissions
|
||||
:label (i18n/label :t/permissions)
|
||||
:accessibility-label :permissions-tab}
|
||||
{:id :about
|
||||
:label (i18n/label :t/about)
|
||||
:accessibility-label :about-tab}])
|
||||
|
||||
(defn traits-section
|
||||
[traits]
|
||||
(when (pos? (count traits))
|
||||
[rn/view
|
||||
[quo/section-label
|
||||
{:section (i18n/label :t/traits)
|
||||
:container-style style/traits-title-container}]
|
||||
[rn/flat-list
|
||||
{:render-fn (fn [{:keys [trait-type value]}]
|
||||
[quo/data-item
|
||||
{:card? true
|
||||
:status :default
|
||||
:size :default
|
||||
:title trait-type
|
||||
:subtitle value
|
||||
:subtitle-type :default
|
||||
:container-style style/traits-item}])
|
||||
:data traits
|
||||
:key :collectibles-list
|
||||
:key-fn :id
|
||||
:num-columns 2
|
||||
:content-container-style style/traits-container}]]))
|
||||
|
||||
(defn activity-item
|
||||
[item]
|
||||
[:<>
|
||||
[quo/divider-date (:timestamp item)]
|
||||
[quo/wallet-activity item]])
|
||||
|
||||
(defn activity-section
|
||||
[]
|
||||
[rn/flat-list
|
||||
{:data temp/collectible-activities
|
||||
:style {:flex 1}
|
||||
:render-fn activity-item}])
|
||||
|
||||
(defn info
|
||||
[chain-id]
|
||||
(let [network (rf/sub [:wallet/network-details-by-chain-id
|
||||
chain-id])
|
||||
network-keyword (get network :network-name)
|
||||
network-name (when network-keyword
|
||||
(string/capitalize (name network-keyword)))]
|
||||
[rn/view
|
||||
{:style style/info-container}
|
||||
[rn/view {:style style/account}
|
||||
[quo/data-item
|
||||
{:card? true
|
||||
:status :default
|
||||
:size :default
|
||||
:title (i18n/label :t/account-title)
|
||||
:subtitle "Collectibles vault"
|
||||
:subtitle-type :account
|
||||
:emoji "🎮"
|
||||
:customization-color :yellow}]]
|
||||
|
||||
[rn/view {:style style/network}
|
||||
[quo/data-item
|
||||
{:card? true
|
||||
:status :default
|
||||
:size :default
|
||||
:title (i18n/label :t/network)
|
||||
:network-image (quo.resources/get-network network-keyword)
|
||||
:subtitle network-name
|
||||
:subtitle-type :network}]]]))
|
||||
|
||||
(defn tabs
|
||||
[_]
|
||||
(let [selected-tab (reagent/atom (:id (first activity-tabs-data)))]
|
||||
(fn [{:keys [traits chain-id] :as _props}]
|
||||
[:<>
|
||||
[quo/tabs
|
||||
{:size 32
|
||||
:style style/tabs
|
||||
:scrollable? true
|
||||
:default-active @selected-tab
|
||||
:data activity-tabs-data
|
||||
:on-change #(reset! selected-tab %)}]
|
||||
(condp = @selected-tab
|
||||
:overview [:<>
|
||||
[info chain-id]
|
||||
[traits-section traits]]
|
||||
:activity [activity-section]
|
||||
nil)])))
|
||||
|
||||
(defn collectible-actions-sheet
|
||||
[]
|
||||
[quo/action-drawer
|
||||
|
@ -162,35 +72,41 @@
|
|||
|
||||
(defn view-internal
|
||||
[{:keys [theme] :as _props}]
|
||||
(let [collectible (rf/sub [:wallet/last-collectible-details])
|
||||
{:keys [collectible-data preview-url
|
||||
collection-data]} collectible
|
||||
{traits :traits
|
||||
collectible-name :name} collectible-data
|
||||
{collection-image :image-url
|
||||
collection-name :name} collection-data
|
||||
chain-id (rf/sub [:wallet/last-collectible-chain-id])]
|
||||
[scroll-page/scroll-page
|
||||
{:navigate-back? true
|
||||
:height 148
|
||||
:page-nav-props {:type :title-description
|
||||
:title collectible-name
|
||||
:description collection-name
|
||||
:right-side [{:icon-name :i/options
|
||||
:on-press #(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content collectible-actions-sheet
|
||||
:theme theme}])}]
|
||||
:picture preview-url}}
|
||||
[rn/view {:style style/container}
|
||||
[rn/view {:style style/preview-container}
|
||||
[rn/image
|
||||
{:source preview-url
|
||||
:style style/preview}]]
|
||||
[header collectible-name collection-name collection-image]
|
||||
[cta-buttons]
|
||||
[tabs
|
||||
{:traits traits
|
||||
:chain-id chain-id}]]]))
|
||||
(let [selected-tab (reagent/atom :overview)
|
||||
on-tab-change #(reset! selected-tab %)]
|
||||
(fn []
|
||||
(let [collectible (rf/sub [:wallet/last-collectible-details])
|
||||
{:keys [collectible-data preview-url
|
||||
collection-data]} collectible
|
||||
{collection-image :image-url
|
||||
collection-name :name} collection-data
|
||||
{collectible-name :name} collectible-data]
|
||||
[scroll-page/scroll-page
|
||||
{:navigate-back? true
|
||||
:height 148
|
||||
:page-nav-props {:type :title-description
|
||||
:title collectible-name
|
||||
:description collection-name
|
||||
:right-side [{:icon-name :i/options
|
||||
:on-press #(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content collectible-actions-sheet
|
||||
:theme theme}])}]
|
||||
:picture preview-url}}
|
||||
[rn/view {:style style/container}
|
||||
[rn/view {:style style/preview-container}
|
||||
[rn/image
|
||||
{:source preview-url
|
||||
:style style/preview}]]
|
||||
[header collectible-name collection-name collection-image]
|
||||
[cta-buttons]
|
||||
[quo/tabs
|
||||
{:size 32
|
||||
:style style/tabs
|
||||
:scrollable? true
|
||||
:default-active @selected-tab
|
||||
:on-change on-tab-change
|
||||
:data tabs-data}]
|
||||
[tabs/view {:selected-tab @selected-tab}]]]))))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
|
|
@ -105,3 +105,20 @@
|
|||
:type :network
|
||||
:network-logo (quo.resources/get-network :ethereum)
|
||||
:network-name "Mainnet"}}])
|
||||
|
||||
(def collectible-about
|
||||
{:cards [{:title "BAYC"
|
||||
:icon :social/link
|
||||
:address "boredapeyachtclub"
|
||||
:customization-color :social/link
|
||||
:on-press #(js/alert "pressed")}
|
||||
{:title "Twitter"
|
||||
:icon :social/twitter
|
||||
:address "@BoredApeYC"
|
||||
:customization-color :social/twitter
|
||||
:on-press #(js/alert "pressed")}
|
||||
{:title "Opensea"
|
||||
:icon :social/opensea
|
||||
:address "Bored Ape Yacht Club"
|
||||
:customization-color :social/opensea
|
||||
:on-press #(js/alert "pressed")}]})
|
||||
|
|
|
@ -38,7 +38,22 @@
|
|||
(assoc last-collectible :preview-url (preview-url (:collectible-data last-collectible))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/last-collectible-chain-id
|
||||
:wallet/last-collectible-details-chain-id
|
||||
:<- [:wallet/last-collectible-details]
|
||||
(fn [collectible]
|
||||
(get-in collectible [:id :contract-id :chain-id])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/last-collectible-details-traits
|
||||
:<- [:wallet/last-collectible-details]
|
||||
(fn [collectible]
|
||||
(get-in collectible [:collectible-data :traits])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/last-collectible-details-owner
|
||||
:<- [:wallet/last-collectible-details]
|
||||
:<- [:wallet]
|
||||
(fn [[collectible wallet]]
|
||||
(let [address (:address (first (:ownership collectible)))
|
||||
account (get-in wallet [:accounts address])]
|
||||
account)))
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
(ns status-im.subs.wallet.collectibles-test
|
||||
(:require
|
||||
[cljs.test :refer [is testing]]
|
||||
[re-frame.db :as rf-db]
|
||||
status-im.subs.root
|
||||
status-im.subs.wallet.collectibles
|
||||
[test-helpers.unit :as h]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def ^:private traits
|
||||
[{:trait-type "Background"
|
||||
:value "Gradient 5"
|
||||
:display-type ""
|
||||
:max-value ""}
|
||||
{:trait-type "Skin"
|
||||
:value "Pale"
|
||||
:display-type ""
|
||||
:max-value ""}
|
||||
{:trait-type "Clothes"
|
||||
:value "Naked"
|
||||
:display-type ""
|
||||
:max-value ""}])
|
||||
|
||||
(def ^:private collectible-owner-wallet
|
||||
{:last-collectible-details {:ownership [{:address "0x1"}]}
|
||||
:accounts {"0x1" {:name "account 1"
|
||||
:color "army"}}})
|
||||
|
||||
(h/deftest-sub :wallet/last-collectible-details-chain-id
|
||||
[sub-name]
|
||||
(testing "correct chain-id of the last collectible should be returned"
|
||||
(swap! rf-db/app-db assoc-in [:wallet :last-collectible-details :id :contract-id :chain-id] "1")
|
||||
(let [result (rf/sub [sub-name])]
|
||||
(is (= "1" result)))))
|
||||
|
||||
(h/deftest-sub :wallet/last-collectible-details-traits
|
||||
[sub-name]
|
||||
(testing "correct traits of the last collectible should be returned"
|
||||
(swap! rf-db/app-db assoc-in [:wallet :last-collectible-details :collectible-data :traits] traits)
|
||||
(let [result (rf/sub [sub-name])]
|
||||
(is (= traits result)))))
|
||||
|
||||
(h/deftest-sub :wallet/last-collectible-details-owner
|
||||
[sub-name]
|
||||
(testing "correct owner of the last collectible should be returned"
|
||||
(swap! rf-db/app-db assoc-in [:wallet] collectible-owner-wallet)
|
||||
(let [result (rf/sub [sub-name])]
|
||||
(is (= {:name "account 1"
|
||||
:color "army"}
|
||||
result)))))
|
|
@ -2449,6 +2449,8 @@
|
|||
"copy-all-details": "Copy all details",
|
||||
"share-details": "Share details",
|
||||
"what-are-you-waiting-for": "What are you waiting for?",
|
||||
"no-relevant-tokens": "No relevant tokens",
|
||||
"on-the-web": "On the web",
|
||||
"sending-with-elipsis": "Sending...",
|
||||
"transaction-confirmed": "Transaction confirmed!",
|
||||
"transacation-finalised": "Transaction finalised!",
|
||||
|
|
Loading…
Reference in New Issue