mirror of
https://github.com/status-im/status-mobile.git
synced 2025-03-01 16:50:58 +00:00
fix(wallet): Improve collectible UX and fix data displayed (#20657)
* Add variant unknown variant for collectibles * Fix blank collectibles listed * Improve `expanded-collectible` animation and add support for different gradient-colors * Make :wallet/collectible-details-owner subscription depend on `wallet/accounts` instead of `:wallet` * Make collectible tabs component more flexible * Remove now unused subscriptions * Improve UX navigation to collectible detail page * Pass the current collectible gradient-color when a collectible is pressed * Fix tests
This commit is contained in:
parent
4c4a8b65d4
commit
7774c4eac1
@ -11,7 +11,7 @@
|
|||||||
(defn fallback
|
(defn fallback
|
||||||
[{:keys [theme opacity]}]
|
[{:keys [theme opacity]}]
|
||||||
[{:opacity opacity}
|
[{:opacity opacity}
|
||||||
{:opacity default-opacity-for-image
|
{:opacity 1
|
||||||
:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
|
:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
|
||||||
:border-style :dashed
|
:border-style :dashed
|
||||||
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
|
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
|
||||||
@ -60,8 +60,13 @@
|
|||||||
:padding-right 0
|
:padding-right 0
|
||||||
:padding-top 4})
|
:padding-top 4})
|
||||||
|
|
||||||
(def card-detail-text
|
(defn card-detail-text
|
||||||
{:flex 1})
|
[empty-name? theme]
|
||||||
|
{:flex 1
|
||||||
|
:margin-right 8
|
||||||
|
:color (if empty-name?
|
||||||
|
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||||
|
(colors/theme-colors colors/neutral-100 colors/white theme))})
|
||||||
|
|
||||||
(defn card-loader
|
(defn card-loader
|
||||||
[opacity]
|
[opacity]
|
||||||
@ -115,6 +120,7 @@
|
|||||||
[{:opacity opacity}
|
[{:opacity opacity}
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:flex-direction :row
|
:flex-direction :row
|
||||||
|
:column-gap 8
|
||||||
:opacity default-opacity-for-image}])
|
:opacity default-opacity-for-image}])
|
||||||
|
|
||||||
(defn supported-file
|
(defn supported-file
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
(ns quo.components.profile.collectible-list-item.view
|
(ns quo.components.profile.collectible-list-item.view
|
||||||
(:require
|
(:require
|
||||||
|
[clojure.string :as string]
|
||||||
[quo.components.avatars.collection-avatar.view :as collection-avatar]
|
[quo.components.avatars.collection-avatar.view :as collection-avatar]
|
||||||
[quo.components.counter.collectible-counter.view :as collectible-counter]
|
[quo.components.counter.collectible-counter.view :as collectible-counter]
|
||||||
[quo.components.icon :as icon]
|
[quo.components.icon :as icon]
|
||||||
@ -21,7 +22,7 @@
|
|||||||
(def cached-load-time 200)
|
(def cached-load-time 200)
|
||||||
(def error-wait-time 800)
|
(def error-wait-time 800)
|
||||||
|
|
||||||
(defn on-load-end
|
(defn animate-loading-image
|
||||||
[{:keys [load-time set-state loader-opacity image-opacity]}]
|
[{:keys [load-time set-state loader-opacity image-opacity]}]
|
||||||
(reanimated/animate loader-opacity 0 timing-options-out)
|
(reanimated/animate loader-opacity 0 timing-options-out)
|
||||||
(reanimated/animate image-opacity 1 timing-options-in)
|
(reanimated/animate image-opacity 1 timing-options-in)
|
||||||
@ -60,12 +61,12 @@
|
|||||||
(assoc prev-state :avatar-loaded? true)))))
|
(assoc prev-state :avatar-loaded? true)))))
|
||||||
|
|
||||||
(defn- fallback-view
|
(defn- fallback-view
|
||||||
[{:keys [label theme image-opacity]}]
|
[{:keys [label theme image-opacity on-load-end]}]
|
||||||
[reanimated/view
|
(rn/use-mount on-load-end)
|
||||||
{:style (style/fallback {:opacity image-opacity
|
[reanimated/view {:style (style/fallback {:opacity image-opacity :theme theme})}
|
||||||
:theme theme})}
|
|
||||||
[rn/view
|
[rn/view
|
||||||
[icon/icon :i/sad {:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}]]
|
[icon/icon :i/sad
|
||||||
|
{:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}]]
|
||||||
[rn/view {:style {:height 4}}]
|
[rn/view {:style {:height 4}}]
|
||||||
[text/text
|
[text/text
|
||||||
{:size :paragraph-2
|
{:size :paragraph-2
|
||||||
@ -93,31 +94,43 @@
|
|||||||
[{:keys [community? avatar-image-src collectible-name theme state set-state]}]
|
[{:keys [community? avatar-image-src collectible-name theme state set-state]}]
|
||||||
(let [loader-opacity (reanimated/use-shared-value 1)
|
(let [loader-opacity (reanimated/use-shared-value 1)
|
||||||
avatar-opacity (reanimated/use-shared-value 0)
|
avatar-opacity (reanimated/use-shared-value 0)
|
||||||
[load-time set-load-time] (rn/use-state (datetime/now))]
|
[load-time set-load-time] (rn/use-state (datetime/now))
|
||||||
|
set-avatar-loaded (fn []
|
||||||
|
(on-load-avatar {:set-state set-state
|
||||||
|
:load-time load-time
|
||||||
|
:loader-opacity loader-opacity
|
||||||
|
:avatar-opacity avatar-opacity}))
|
||||||
|
empty-name? (string/blank? collectible-name)]
|
||||||
|
(rn/use-mount (fn []
|
||||||
|
(when (string/blank? avatar-image-src)
|
||||||
|
(set-avatar-loaded))))
|
||||||
[rn/view {:style style/card-details-container}
|
[rn/view {:style style/card-details-container}
|
||||||
[reanimated/view {:style (style/avatar-container avatar-opacity)}
|
[reanimated/view {:style (style/avatar-container avatar-opacity)}
|
||||||
(if community?
|
(cond
|
||||||
[preview-list/view
|
(string/blank? avatar-image-src)
|
||||||
{:type :communities
|
[loading-square theme]
|
||||||
:size :size-20}
|
|
||||||
|
community?
|
||||||
|
[preview-list/view {:type :communities :size :size-20}
|
||||||
[avatar-image-src]]
|
[avatar-image-src]]
|
||||||
|
|
||||||
|
:else
|
||||||
[collection-avatar/view
|
[collection-avatar/view
|
||||||
{:size :size-20
|
{:size :size-20
|
||||||
:on-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
:on-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
||||||
:on-load-end #(on-load-avatar {:set-state set-state
|
:on-load-end set-avatar-loaded
|
||||||
:load-time load-time
|
|
||||||
:loader-opacity loader-opacity
|
|
||||||
:avatar-opacity avatar-opacity})
|
|
||||||
:image avatar-image-src}])
|
:image avatar-image-src}])
|
||||||
[rn/view {:style {:width 8}}]
|
|
||||||
[text/text
|
[text/text
|
||||||
{:size :paragraph-1
|
{:size :paragraph-1
|
||||||
:weight :semi-bold
|
:weight :semi-bold
|
||||||
:ellipsize-mode :tail
|
:ellipsize-mode :tail
|
||||||
:number-of-lines 1
|
:number-of-lines 1
|
||||||
:style style/card-detail-text}
|
:style (style/card-detail-text empty-name? theme)}
|
||||||
collectible-name]]
|
(if empty-name?
|
||||||
(when (not (:avatar-loaded? state))
|
(i18n/label :t/unknown)
|
||||||
|
collectible-name)]]
|
||||||
|
|
||||||
|
(when-not (:avatar-loaded? state)
|
||||||
[reanimated/view {:style (style/card-loader loader-opacity)}
|
[reanimated/view {:style (style/card-loader loader-opacity)}
|
||||||
[loading-square theme]
|
[loading-square theme]
|
||||||
[loading-message theme]])]))
|
[loading-message theme]])]))
|
||||||
@ -128,40 +141,44 @@
|
|||||||
(let [theme (quo.theme/use-theme)
|
(let [theme (quo.theme/use-theme)
|
||||||
loader-opacity (reanimated/use-shared-value (if supported-file? 1 0))
|
loader-opacity (reanimated/use-shared-value (if supported-file? 1 0))
|
||||||
image-opacity (reanimated/use-shared-value (if supported-file? 0 1))
|
image-opacity (reanimated/use-shared-value (if supported-file? 0 1))
|
||||||
[load-time set-load-time] (rn/use-state (datetime/now))]
|
[load-time set-load-time] (rn/use-state (datetime/now))
|
||||||
|
set-image-loaded (fn []
|
||||||
|
(animate-loading-image {:load-time load-time
|
||||||
|
:set-state set-state
|
||||||
|
:loader-opacity loader-opacity
|
||||||
|
:image-opacity image-opacity}))]
|
||||||
[rn/view {:style (style/card-view-container theme)}
|
[rn/view {:style (style/card-view-container theme)}
|
||||||
[rn/view {:style {:aspect-ratio 1}}
|
[rn/view {:style {:aspect-ratio 1}}
|
||||||
(cond
|
(cond
|
||||||
(:image-error? state)
|
(:image-error? state) [fallback-view
|
||||||
[fallback-view
|
{:image-opacity image-opacity
|
||||||
{:image-opacity image-opacity
|
:on-load-end set-image-loaded
|
||||||
:theme theme
|
:theme theme
|
||||||
:label (i18n/label :t/cant-fetch-info)}]
|
:label (i18n/label :t/cant-fetch-info)}]
|
||||||
|
(not supported-file?) [fallback-view
|
||||||
|
{:image-opacity image-opacity
|
||||||
|
:on-load-end set-image-loaded
|
||||||
|
:theme theme
|
||||||
|
:label (i18n/label :t/unsupported-file)}]
|
||||||
|
(not (:image-loaded? state)) [loading-image
|
||||||
|
{:loader-opacity loader-opacity
|
||||||
|
:theme theme
|
||||||
|
:gradient-color-index gradient-color-index}])
|
||||||
|
|
||||||
(not supported-file?)
|
|
||||||
[fallback-view
|
|
||||||
{:image-opacity image-opacity
|
|
||||||
:theme theme
|
|
||||||
:label (i18n/label :t/unsupported-file)}]
|
|
||||||
|
|
||||||
(not (:image-loaded? state))
|
|
||||||
[loading-image
|
|
||||||
{:loader-opacity loader-opacity
|
|
||||||
:theme theme
|
|
||||||
:gradient-color-index gradient-color-index}])
|
|
||||||
(when supported-file?
|
(when supported-file?
|
||||||
[reanimated/view {:style (style/supported-file image-opacity)}
|
[reanimated/view {:style (style/supported-file image-opacity)}
|
||||||
[rn/image
|
[rn/image
|
||||||
{:style style/image
|
{:style style/image
|
||||||
:on-load #(on-load % set-state)
|
:on-load #(on-load % set-state)
|
||||||
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
||||||
:on-load-end #(on-load-end {:load-time load-time
|
:on-load-end set-image-loaded
|
||||||
:set-state set-state
|
|
||||||
:loader-opacity loader-opacity
|
|
||||||
:image-opacity image-opacity})
|
|
||||||
:on-error #(on-load-error set-state)
|
:on-error #(on-load-error set-state)
|
||||||
:source image-src}]])]
|
:source image-src}]])]
|
||||||
(when (and (:image-loaded? state) (not (:image-error? state)) counter)
|
|
||||||
|
(when (and (or (:image-loaded? state)
|
||||||
|
(not supported-file?))
|
||||||
|
(not (:image-error? state))
|
||||||
|
counter)
|
||||||
[collectible-counter/view
|
[collectible-counter/view
|
||||||
{:container-style style/collectible-counter
|
{:container-style style/collectible-counter
|
||||||
:size :size-24
|
:size :size-24
|
||||||
@ -206,10 +223,10 @@
|
|||||||
{:style style/image
|
{:style style/image
|
||||||
:on-load #(on-load % set-state)
|
:on-load #(on-load % set-state)
|
||||||
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
||||||
:on-load-end #(on-load-end {:load-time load-time
|
:on-load-end #(animate-loading-image {:load-time load-time
|
||||||
:set-state set-state
|
:set-state set-state
|
||||||
:loader-opacity loader-opacity
|
:loader-opacity loader-opacity
|
||||||
:image-opacity image-opacity})
|
:image-opacity image-opacity})
|
||||||
:on-error #(on-load-error set-state)
|
:on-error #(on-load-error set-state)
|
||||||
:source image-src}]])
|
:source image-src}]])
|
||||||
(when (and (:image-loaded? state) (not (:image-error? state)) counter)
|
(when (and (:image-loaded? state) (not (:image-error? state)) counter)
|
||||||
|
@ -11,38 +11,24 @@
|
|||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.reanimated :as reanimated]
|
[react-native.reanimated :as reanimated]
|
||||||
[schema.core :as schema]
|
[schema.core :as schema]
|
||||||
[utils.datetime :as datetime]
|
|
||||||
[utils.i18n :as i18n]))
|
[utils.i18n :as i18n]))
|
||||||
|
|
||||||
(def timing-options-out 650)
|
(def loader-out 650)
|
||||||
(def timing-options-in 1000)
|
(def image-in 1000)
|
||||||
(def first-load-time 500)
|
|
||||||
(def cached-load-time 200)
|
|
||||||
(def error-wait-time 800)
|
(def error-wait-time 800)
|
||||||
|
|
||||||
(defn on-load-end
|
(defn on-load-end
|
||||||
[{:keys [load-time set-state loader-opacity image-opacity]}]
|
[{:keys [loader-opacity image-opacity]}]
|
||||||
(reanimated/animate loader-opacity 0 timing-options-out)
|
(reanimated/animate loader-opacity 0 loader-out)
|
||||||
(reanimated/animate image-opacity 1 timing-options-in)
|
(reanimated/animate image-opacity 1 image-in))
|
||||||
(if (> load-time cached-load-time)
|
|
||||||
(js/setTimeout
|
|
||||||
(fn []
|
|
||||||
(set-state (fn [prev-state]
|
|
||||||
(assoc prev-state :image-loaded? true))))
|
|
||||||
first-load-time)
|
|
||||||
(set-state (fn [prev-state]
|
|
||||||
(assoc prev-state :image-loaded? true)))))
|
|
||||||
|
|
||||||
(defn on-load-error
|
(defn on-load-error
|
||||||
[set-state]
|
[set-error]
|
||||||
(js/setTimeout (fn []
|
(js/setTimeout set-error error-wait-time))
|
||||||
(set-state (fn [prev-state] (assoc prev-state :image-error? true))))
|
|
||||||
error-wait-time))
|
|
||||||
|
|
||||||
(defn- loading-image
|
(defn- loading-image
|
||||||
[{:keys [theme gradient-color-index loader-opacity aspect-ratio]}]
|
[{:keys [theme gradient-color-index loader-opacity aspect-ratio]}]
|
||||||
[reanimated/view
|
[reanimated/view {:style (style/loading-image-with-opacity loader-opacity)}
|
||||||
{:style (style/loading-image-with-opacity loader-opacity)}
|
|
||||||
[gradients/view
|
[gradients/view
|
||||||
{:theme theme
|
{:theme theme
|
||||||
:container-style (style/gradient-view aspect-ratio)
|
:container-style (style/gradient-view aspect-ratio)
|
||||||
@ -67,62 +53,64 @@
|
|||||||
:style {:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}}
|
:style {:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}}
|
||||||
label]])
|
label]])
|
||||||
|
|
||||||
|
(defn- collectible-image
|
||||||
|
[{:keys [aspect-ratio theme gradient-color-index supported-file? set-error native-ID
|
||||||
|
square? image-src on-collectible-load counter]}]
|
||||||
|
(let [loader-opacity (reanimated/use-shared-value (if supported-file? 1 0))
|
||||||
|
image-opacity (reanimated/use-shared-value (if supported-file? 0 1))]
|
||||||
|
[:<>
|
||||||
|
[loading-image
|
||||||
|
{:aspect-ratio aspect-ratio
|
||||||
|
:loader-opacity loader-opacity
|
||||||
|
:theme theme
|
||||||
|
:gradient-color-index gradient-color-index}]
|
||||||
|
|
||||||
|
[reanimated/view {:style (style/supported-file image-opacity)}
|
||||||
|
[rn/image
|
||||||
|
{:style (style/image square? aspect-ratio theme)
|
||||||
|
:source image-src
|
||||||
|
:native-ID native-ID
|
||||||
|
:on-load-end (fn []
|
||||||
|
(on-load-end {:loader-opacity loader-opacity
|
||||||
|
:image-opacity image-opacity}))
|
||||||
|
:on-error #(on-load-error set-error)
|
||||||
|
:on-load on-collectible-load}]
|
||||||
|
(when counter
|
||||||
|
[counter-view counter])
|
||||||
|
[rn/view {:style (style/collectible-border theme)}]]]))
|
||||||
|
|
||||||
(defn view-internal
|
(defn view-internal
|
||||||
[{:keys [container-style square? on-press counter image-src native-ID supported-file?
|
[{:keys [container-style square? on-press counter image-src native-ID supported-file?
|
||||||
on-collectible-load aspect-ratio]}]
|
on-collectible-load aspect-ratio gradient-color-index]
|
||||||
(let [theme (quo.theme/use-theme)
|
:or {gradient-color-index :gradient-1
|
||||||
loader-opacity (reanimated/use-shared-value
|
on-collectible-load (fn [])}}]
|
||||||
(if supported-file? 1 0))
|
(let [theme (quo.theme/use-theme)
|
||||||
image-opacity (reanimated/use-shared-value
|
[error? set-error] (rn/use-state (or (nil? image-src)
|
||||||
(if supported-file? 0 1))
|
(string/blank? image-src)))]
|
||||||
[load-time set-load-time] (rn/use-state (datetime/now))
|
|
||||||
[state set-state] (rn/use-state {:image-loaded? false
|
|
||||||
:image-error? (or (nil? image-src)
|
|
||||||
(string/blank?
|
|
||||||
image-src))})]
|
|
||||||
[rn/pressable
|
[rn/pressable
|
||||||
{:on-press (when (and (not (:image-error? state)) supported-file?) on-press)
|
{:style (merge container-style (style/container aspect-ratio))
|
||||||
:accessibility-label :expanded-collectible
|
:accessibility-label :expanded-collectible
|
||||||
:style (merge container-style
|
:on-press (when (and (not error?) supported-file?)
|
||||||
(style/container aspect-ratio))}
|
on-press)}
|
||||||
(cond
|
(if (or (not supported-file?) error?)
|
||||||
(not supported-file?)
|
|
||||||
[fallback-view
|
[fallback-view
|
||||||
{:aspect-ratio aspect-ratio
|
{:label (i18n/label (if-not supported-file?
|
||||||
:label (i18n/label :t/unsupported-file)
|
:t/unsupported-file
|
||||||
:counter counter
|
:t/cant-fetch-info))
|
||||||
:theme theme
|
|
||||||
:on-mount on-collectible-load}]
|
|
||||||
|
|
||||||
(:image-error? state)
|
|
||||||
[fallback-view
|
|
||||||
{:label (i18n/label :t/cant-fetch-info)
|
|
||||||
:counter counter
|
:counter counter
|
||||||
:theme theme
|
:theme theme
|
||||||
:on-mount on-collectible-load}]
|
:on-mount on-collectible-load}]
|
||||||
|
[collectible-image
|
||||||
(not (:image-loaded? state))
|
|
||||||
[loading-image
|
|
||||||
{:aspect-ratio aspect-ratio
|
{:aspect-ratio aspect-ratio
|
||||||
:loader-opacity loader-opacity
|
|
||||||
:theme theme
|
:theme theme
|
||||||
:gradient-color-index :gradient-5}])
|
:supported-file? supported-file?
|
||||||
(when supported-file?
|
:set-error set-error
|
||||||
[reanimated/view {:style (style/supported-file image-opacity)}
|
:native-ID native-ID
|
||||||
[rn/image
|
:square? square?
|
||||||
{:style (style/image square? aspect-ratio theme)
|
:image-src image-src
|
||||||
:source image-src
|
:on-collectible-load on-collectible-load
|
||||||
:native-ID native-ID
|
:counter counter
|
||||||
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
:gradient-color-index gradient-color-index}])]))
|
||||||
:on-load-end #(on-load-end {:load-time load-time
|
|
||||||
:set-state set-state
|
|
||||||
:loader-opacity loader-opacity
|
|
||||||
:image-opacity image-opacity})
|
|
||||||
:on-error #(on-load-error set-state)
|
|
||||||
:on-load on-collectible-load}]
|
|
||||||
(when counter
|
|
||||||
[counter-view counter])
|
|
||||||
[rn/view {:style (style/collectible-border theme)}]])]))
|
|
||||||
|
|
||||||
(def ?schema
|
(def ?schema
|
||||||
[:=>
|
[:=>
|
||||||
@ -137,7 +125,8 @@
|
|||||||
[:square? {:optional true} [:maybe boolean?]]
|
[:square? {:optional true} [:maybe boolean?]]
|
||||||
[:counter {:optional true} [:maybe string?]]
|
[:counter {:optional true} [:maybe string?]]
|
||||||
[:on-press {:optional true} [:maybe fn?]]
|
[:on-press {:optional true} [:maybe fn?]]
|
||||||
[:on-collectible-load {:optional true} [:maybe fn?]]]]]
|
[:on-collectible-load {:optional true} [:maybe fn?]]
|
||||||
|
[:gradient-color-index {:optional true} [:maybe keyword?]]]]]
|
||||||
:any])
|
:any])
|
||||||
|
|
||||||
(def view (schema/instrument #'view-internal ?schema))
|
(def view (schema/instrument #'view-internal ?schema))
|
||||||
|
@ -11,9 +11,7 @@
|
|||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn- on-collectible-press
|
(def on-collectible-press #(rf/dispatch [:wallet/navigate-to-collectible-details %]))
|
||||||
[{:keys [id]} aspect-ratio]
|
|
||||||
(rf/dispatch [:wallet/get-collectible-details id aspect-ratio]))
|
|
||||||
|
|
||||||
(defn- on-collectible-long-press
|
(defn- on-collectible-long-press
|
||||||
[{:keys [preview-url collectible-details id]}]
|
[{:keys [preview-url collectible-details id]}]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
(ns status-im.contexts.wallet.collectible.events
|
(ns status-im.contexts.wallet.collectible.events
|
||||||
(:require [camel-snake-kebab.extras :as cske]
|
(:require [camel-snake-kebab.extras :as cske]
|
||||||
|
[clojure.string :as string]
|
||||||
[react-native.platform :as platform]
|
[react-native.platform :as platform]
|
||||||
[status-im.contexts.wallet.collectible.utils :as collectible-utils]
|
[status-im.contexts.wallet.collectible.utils :as collectible-utils]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
@ -44,13 +45,6 @@
|
|||||||
|
|
||||||
(rf/reg-event-fx :wallet/clear-stored-collectibles clear-stored-collectibles)
|
(rf/reg-event-fx :wallet/clear-stored-collectibles clear-stored-collectibles)
|
||||||
|
|
||||||
(defn store-last-collectible-details
|
|
||||||
[{:keys [db]} [collectible]]
|
|
||||||
{:db (assoc-in db [:wallet :last-collectible-details] collectible)
|
|
||||||
:dispatch [:navigate-to :screen/wallet.collectible]})
|
|
||||||
|
|
||||||
(rf/reg-event-fx :wallet/store-last-collectible-details store-last-collectible-details)
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet/request-new-collectibles-for-account
|
:wallet/request-new-collectibles-for-account
|
||||||
(fn [{:keys [db]} [{:keys [request-id account amount]}]]
|
(fn [{:keys [db]} [{:keys [request-id account amount]}]]
|
||||||
@ -166,39 +160,58 @@
|
|||||||
[:dispatch [:wallet/flush-collectibles-fetched]])]})))
|
[:dispatch [:wallet/flush-collectibles-fetched]])]})))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet/get-collectible-details
|
:wallet/navigate-to-collectible-details
|
||||||
(fn [{:keys [db]} [collectible-id aspect-ratio]]
|
(fn [{:keys [db]}
|
||||||
|
[{{collectible-id :id :as collectible} :collectible
|
||||||
|
aspect-ratio :aspect-ratio
|
||||||
|
gradient-color :gradient-color}]]
|
||||||
(let [request-id 0
|
(let [request-id 0
|
||||||
collectible-id-converted (cske/transform-keys transforms/->PascalCaseKeyword collectible-id)
|
collectible-id-converted (cske/transform-keys transforms/->PascalCaseKeyword collectible-id)
|
||||||
data-type (collectible-data-types :details)
|
data-type (collectible-data-types :details)
|
||||||
request-params [request-id [collectible-id-converted] data-type]]
|
request-params [request-id [collectible-id-converted] data-type]]
|
||||||
{:db (assoc-in db [:wallet :last-collectible-aspect-ratio] aspect-ratio)
|
{:db (assoc-in db
|
||||||
|
[:wallet :ui :collectible]
|
||||||
|
{:details collectible
|
||||||
|
:aspect-ratio aspect-ratio
|
||||||
|
:gradient-color gradient-color})
|
||||||
:fx [[:json-rpc/call
|
:fx [[:json-rpc/call
|
||||||
[{:method "wallet_getCollectiblesByUniqueIDAsync"
|
[{:method "wallet_getCollectiblesByUniqueIDAsync"
|
||||||
:params request-params
|
:params request-params
|
||||||
:on-error (fn [error]
|
:on-error (fn [error]
|
||||||
(log/error "failed to request collectible"
|
(log/error "failed to request collectible"
|
||||||
{:event :wallet/get-collectible-details
|
{:event :wallet/navigate-to-collectible-details
|
||||||
:error error
|
:error error
|
||||||
:params request-params}))}]]]})))
|
:params request-params}))}]]
|
||||||
|
;; We delay the navigation because we need re-frame to update the DB on time.
|
||||||
|
;; By doing it, we skip a blink while visiting the collectible detail page.
|
||||||
|
[:dispatch-later
|
||||||
|
{:ms 1
|
||||||
|
:dispatch [:navigate-to :screen/wallet.collectible]}]]})))
|
||||||
|
|
||||||
|
(defn- keep-not-empty-value
|
||||||
|
[old-value new-value]
|
||||||
|
(if (or (string/blank? new-value) (nil? new-value))
|
||||||
|
old-value
|
||||||
|
new-value))
|
||||||
|
|
||||||
|
(def merge-skipping-empty-values (partial merge-with keep-not-empty-value))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet/get-collectible-details-done
|
:wallet/get-collectible-details-done
|
||||||
(fn [_ [{:keys [message]}]]
|
(fn [{db :db} [{:keys [message]}]]
|
||||||
(let [response (cske/transform-keys transforms/->kebab-case-keyword
|
(let [response (cske/transform-keys transforms/->kebab-case-keyword
|
||||||
(transforms/json->clj message))
|
(transforms/json->clj message))
|
||||||
{:keys [collectibles]} response
|
{[collectible] :collectibles} response]
|
||||||
collectible (first collectibles)]
|
|
||||||
(if collectible
|
(if collectible
|
||||||
{:fx [[:dispatch [:wallet/store-last-collectible-details collectible]]]}
|
{:db (update-in db [:wallet :ui :collectible :details] merge-skipping-empty-values collectible)}
|
||||||
(log/error "failed to get collectible details"
|
(log/error "failed to get collectible details"
|
||||||
{:event :wallet/get-collectible-details-done
|
{:event :wallet/get-collectible-details-done
|
||||||
:response response})))))
|
:response response})))))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet/clear-last-collectible-details
|
:wallet/clear-collectible-details
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
{:db (update-in db [:wallet] dissoc :last-collectible-details :last-collectible-aspect-ratio)}))
|
{:db (update-in db [:wallet :ui] dissoc :collectible)}))
|
||||||
|
|
||||||
(rf/reg-event-fx :wallet/trigger-share-collectible
|
(rf/reg-event-fx :wallet/trigger-share-collectible
|
||||||
(fn [_ [{:keys [title uri]}]]
|
(fn [_ [{:keys [title uri]}]]
|
||||||
|
@ -43,18 +43,6 @@
|
|||||||
|
|
||||||
(is (match? result-db expected-db))))))
|
(is (match? result-db expected-db))))))
|
||||||
|
|
||||||
(deftest store-last-collectible-details-test
|
|
||||||
(testing "store-last-collectible-details"
|
|
||||||
(let [db {:wallet {}}
|
|
||||||
last-collectible {:description "Pandaria"
|
|
||||||
:image-url "https://..."}
|
|
||||||
expected-db {:wallet {:last-collectible-details {:description "Pandaria"
|
|
||||||
:image-url "https://..."}}}
|
|
||||||
effects (events/store-last-collectible-details {:db db}
|
|
||||||
[last-collectible])
|
|
||||||
result-db (:db effects)]
|
|
||||||
(is (match? result-db expected-db)))))
|
|
||||||
|
|
||||||
(deftest request-new-collectibles-for-account-from-signal-test
|
(deftest request-new-collectibles-for-account-from-signal-test
|
||||||
(testing "request new collectibles for account from signal"
|
(testing "request new collectibles for account from signal"
|
||||||
(let [db {:wallet {}}
|
(let [db {:wallet {}}
|
||||||
|
@ -8,12 +8,11 @@
|
|||||||
(def ^:private link-card-space 28)
|
(def ^:private link-card-space 28)
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[{:keys [collectible-data]}]
|
||||||
(let [window-width (rf/sub [:dimensions/window-width])
|
(let [window-width (rf/sub [:dimensions/window-width])
|
||||||
item-width (- (/ window-width 2) link-card-space)
|
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)
|
||||||
link-card-container-style (style/link-card item-width)
|
collectible-about {:cards []}]
|
||||||
collectible-about {:cards []}]
|
|
||||||
[:<>
|
[:<>
|
||||||
[rn/view {:style style/title}
|
[rn/view {:style style/title}
|
||||||
[quo/text
|
[quo/text
|
||||||
|
@ -21,27 +21,25 @@
|
|||||||
:container-style style/traits-item}])
|
:container-style style/traits-item}])
|
||||||
|
|
||||||
(defn- traits-section
|
(defn- traits-section
|
||||||
[]
|
[traits]
|
||||||
(let [traits (rf/sub [:wallet/last-collectible-details-traits])]
|
[rn/view
|
||||||
(when (pos? (count traits))
|
[quo/section-label
|
||||||
[rn/view
|
{:section (i18n/label :t/traits)
|
||||||
[quo/section-label
|
:container-style style/traits-title-container}]
|
||||||
{:section (i18n/label :t/traits)
|
[rn/flat-list
|
||||||
:container-style style/traits-title-container}]
|
{:render-fn trait-item
|
||||||
[rn/flat-list
|
:data traits
|
||||||
{:render-fn trait-item
|
:key :collectibles-list
|
||||||
:data traits
|
:key-fn :id
|
||||||
:key :collectibles-list
|
:num-columns 2
|
||||||
:key-fn :id
|
:content-container-style style/traits-container}]])
|
||||||
:num-columns 2
|
|
||||||
:content-container-style style/traits-container}]])))
|
|
||||||
|
|
||||||
(defn- info
|
(defn- info
|
||||||
[]
|
[{:keys [chain-id account]}]
|
||||||
(let [chain-id (rf/sub [:wallet/last-collectible-details-chain-id])
|
(let [{:keys [network-name]} (rf/sub [:wallet/network-details-by-chain-id chain-id])
|
||||||
{:keys [network-name]} (rf/sub [:wallet/network-details-by-chain-id chain-id])
|
subtitle (some-> network-name
|
||||||
subtitle (string/capitalize (name (or network-name "")))
|
name
|
||||||
{:keys [name emoji color]} (rf/sub [:wallet/last-collectible-details-owner])]
|
string/capitalize)]
|
||||||
[rn/view {:style style/info-container}
|
[rn/view {:style style/info-container}
|
||||||
[rn/view {:style style/account}
|
[rn/view {:style style/account}
|
||||||
[quo/data-item
|
[quo/data-item
|
||||||
@ -49,10 +47,10 @@
|
|||||||
:status :default
|
:status :default
|
||||||
:size :default
|
:size :default
|
||||||
:title (i18n/label :t/account-title)
|
:title (i18n/label :t/account-title)
|
||||||
:subtitle name
|
|
||||||
:emoji emoji
|
|
||||||
:subtitle-type :account
|
:subtitle-type :account
|
||||||
:customization-color color}]]
|
:subtitle (:name account)
|
||||||
|
:emoji (:emoji account)
|
||||||
|
:customization-color (:color account)}]]
|
||||||
[rn/view {:style style/network}
|
[rn/view {:style style/network}
|
||||||
[quo/data-item
|
[quo/data-item
|
||||||
{:subtitle-type :network
|
{:subtitle-type :network
|
||||||
@ -64,7 +62,12 @@
|
|||||||
:subtitle subtitle}]]]))
|
:subtitle subtitle}]]]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[collectible]
|
||||||
[:<>
|
(let [owner-account (rf/sub [:wallet/collectible-details-owner collectible])
|
||||||
[info]
|
traits (-> collectible :collectible-data :traits)]
|
||||||
[traits-section]])
|
[:<>
|
||||||
|
[info
|
||||||
|
{:chain-id (-> collectible :id :contract-id :chain-id)
|
||||||
|
:account owner-account}]
|
||||||
|
(when (pos? (count traits))
|
||||||
|
[traits-section traits])]))
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
[status-im.contexts.wallet.collectible.tabs.overview.view :as overview]))
|
[status-im.contexts.wallet.collectible.tabs.overview.view :as overview]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [selected-tab]}]
|
[{:keys [selected-tab collectible]}]
|
||||||
(case selected-tab
|
(case selected-tab
|
||||||
:overview [overview/view]
|
:overview [overview/view collectible]
|
||||||
:about [about/view]
|
:about [about/view collectible]
|
||||||
:activity [activity/view]
|
:activity [activity/view]
|
||||||
nil))
|
nil))
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
:balance
|
:balance
|
||||||
js/parseInt))
|
js/parseInt))
|
||||||
|
|
||||||
(def ^:const supported-collectible-types
|
(def supported-collectible-types
|
||||||
#{"image/jpeg"
|
#{"image/jpeg"
|
||||||
"image/gif"
|
"image/gif"
|
||||||
"image/bmp"
|
"image/bmp"
|
||||||
|
@ -76,11 +76,10 @@
|
|||||||
(defn navigate-back-and-clear-collectible
|
(defn navigate-back-and-clear-collectible
|
||||||
[]
|
[]
|
||||||
(rf/dispatch [:navigate-back])
|
(rf/dispatch [:navigate-back])
|
||||||
(js/setTimeout #(rf/dispatch [:wallet/clear-last-collectible-details]) 700))
|
(rf/dispatch [:wallet/clear-collectible-details]))
|
||||||
|
|
||||||
(defn animated-header
|
(defn animated-header
|
||||||
[{:keys [scroll-amount title-opacity page-nav-type picture title description theme
|
[{:keys [scroll-amount title-opacity page-nav-type picture title description theme id]}]
|
||||||
id]}]
|
|
||||||
(let [blur-amount (header-animations/use-blur-amount scroll-amount)
|
(let [blur-amount (header-animations/use-blur-amount scroll-amount)
|
||||||
layer-opacity (header-animations/use-layer-opacity
|
layer-opacity (header-animations/use-layer-opacity
|
||||||
scroll-amount
|
scroll-amount
|
||||||
@ -149,8 +148,9 @@
|
|||||||
(let [title-ref (rn/use-ref-atom nil)
|
(let [title-ref (rn/use-ref-atom nil)
|
||||||
set-title-ref (rn/use-callback #(reset! title-ref %))
|
set-title-ref (rn/use-callback #(reset! title-ref %))
|
||||||
animation-shared-element-id (rf/sub [:animation-shared-element-id])
|
animation-shared-element-id (rf/sub [:animation-shared-element-id])
|
||||||
collectible-owner (rf/sub [:wallet/last-collectible-details-owner])
|
collectible-owner (rf/sub [:wallet/collectible-details-owner collectible])
|
||||||
aspect-ratio (rf/sub [:wallet/last-collectible-aspect-ratio])
|
aspect-ratio (rf/sub [:wallet/collectible-aspect-ratio])
|
||||||
|
gradient-color (rf/sub [:wallet/collectible-gradient-color])
|
||||||
{:keys [id
|
{:keys [id
|
||||||
preview-url
|
preview-url
|
||||||
collection-data
|
collection-data
|
||||||
@ -181,35 +181,36 @@
|
|||||||
[rn/view
|
[rn/view
|
||||||
[gradient-layer preview-uri]
|
[gradient-layer preview-uri]
|
||||||
[quo/expanded-collectible
|
[quo/expanded-collectible
|
||||||
{:aspect-ratio aspect-ratio
|
{:aspect-ratio aspect-ratio
|
||||||
:image-src preview-uri
|
:image-src preview-uri
|
||||||
:container-style (style/preview-container)
|
:container-style (style/preview-container)
|
||||||
:counter (utils/collectible-owned-counter total-owned)
|
:gradient-color-index gradient-color
|
||||||
:native-ID (when (= animation-shared-element-id token-id) :shared-element)
|
:counter (utils/collectible-owned-counter total-owned)
|
||||||
:supported-file? (utils/supported-file? (:animation-media-type collectible-data))
|
:native-ID (when (= animation-shared-element-id token-id) :shared-element)
|
||||||
:on-press (fn []
|
:supported-file? (utils/supported-file? (:animation-media-type collectible-data))
|
||||||
(if svg?
|
:on-press (fn []
|
||||||
(js/alert "Can't visualize SVG images in lightbox")
|
(if svg?
|
||||||
(rf/dispatch
|
(js/alert "Can't visualize SVG images in lightbox")
|
||||||
[:lightbox/navigate-to-lightbox
|
(rf/dispatch
|
||||||
token-id
|
[:lightbox/navigate-to-lightbox
|
||||||
{:images [collectible-image]
|
token-id
|
||||||
:index 0
|
{:images [collectible-image]
|
||||||
:on-options-press #(rf/dispatch [:show-bottom-sheet
|
:index 0
|
||||||
{:content
|
:on-options-press #(rf/dispatch [:show-bottom-sheet
|
||||||
(fn []
|
{:content
|
||||||
[options-drawer/view
|
(fn []
|
||||||
{:name collectible-name
|
[options-drawer/view
|
||||||
:image
|
{:name collectible-name
|
||||||
preview-uri
|
:image
|
||||||
:id id}])}])}])))
|
preview-uri
|
||||||
:on-collectible-load (fn []
|
:id id}])}])}])))
|
||||||
;; We need to delay the measurement because the
|
:on-collectible-load (fn []
|
||||||
;; navigation has an animation
|
;; We need to delay the measurement because the
|
||||||
(js/setTimeout
|
;; navigation has an animation
|
||||||
#(some-> @title-ref
|
(js/setTimeout
|
||||||
(oops/ocall "measureInWindow" set-title-bottom))
|
#(some-> @title-ref
|
||||||
300))}]]
|
(oops/ocall "measureInWindow" set-title-bottom))
|
||||||
|
300))}]]
|
||||||
[rn/view {:style (style/background-color theme)}
|
[rn/view {:style (style/background-color theme)}
|
||||||
[header collectible-name collection-name collection-image set-title-ref]
|
[header collectible-name collection-name collection-image set-title-ref]
|
||||||
[cta-buttons
|
[cta-buttons
|
||||||
@ -225,39 +226,43 @@
|
|||||||
:default-active @selected-tab
|
:default-active @selected-tab
|
||||||
:on-change on-tab-change
|
:on-change on-tab-change
|
||||||
:data tabs-data}]
|
:data tabs-data}]
|
||||||
[tabs/view {:selected-tab @selected-tab}]]]))))
|
[tabs/view
|
||||||
|
{:selected-tab @selected-tab
|
||||||
|
:collectible collectible}]]]))))
|
||||||
|
|
||||||
|
(defn- get-title-bottom-y-position
|
||||||
|
[y-element-position element-height]
|
||||||
|
(let [{:keys [top]} (safe-area/get-insets)
|
||||||
|
title-height -56]
|
||||||
|
(+ y-element-position
|
||||||
|
element-height
|
||||||
|
title-height
|
||||||
|
(when platform/ios? (* top -2)))))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[_]
|
[_]
|
||||||
(let [{:keys [top]} (safe-area/get-insets)
|
(let [{:keys [top]} (safe-area/get-insets)
|
||||||
theme (quo.theme/use-theme)
|
theme (quo.theme/use-theme)
|
||||||
title-bottom-coord (rn/use-ref-atom 0)
|
title-bottom-coord (rn/use-ref-atom 0)
|
||||||
set-title-bottom (rn/use-callback
|
set-title-bottom (rn/use-callback
|
||||||
(fn [_ y _ height]
|
(fn [_ y _ height]
|
||||||
(reset! title-bottom-coord
|
(reset! title-bottom-coord
|
||||||
(+ y
|
(get-title-bottom-y-position y height))))
|
||||||
height
|
scroll-amount (reanimated/use-shared-value 0)
|
||||||
-56
|
title-opacity (reanimated/use-shared-value 0)
|
||||||
(when platform/ios?
|
{:keys [collection-data
|
||||||
(* top -2))))))
|
collectible-data
|
||||||
scroll-amount (reanimated/use-shared-value 0)
|
preview-url]
|
||||||
title-opacity (reanimated/use-shared-value 0)
|
:as collectible} (rf/sub [:wallet/collectible-details])]
|
||||||
collectible (rf/sub [:wallet/last-collectible-details])
|
|
||||||
{:keys [preview-url
|
|
||||||
collection-data
|
|
||||||
collectible-data]} collectible
|
|
||||||
{preview-uri :uri} preview-url
|
|
||||||
{collectible-name :name} collectible-data
|
|
||||||
{collection-name :name} collection-data]
|
|
||||||
[rn/view {:style (style/background-color theme)}
|
[rn/view {:style (style/background-color theme)}
|
||||||
[animated-header
|
[animated-header
|
||||||
{:id (:id collectible)
|
{:id (:id collectible)
|
||||||
:scroll-amount scroll-amount
|
:scroll-amount scroll-amount
|
||||||
:title-opacity title-opacity
|
:title-opacity title-opacity
|
||||||
:page-nav-type :title-description
|
:page-nav-type :title-description
|
||||||
:picture preview-uri
|
:picture (:uri preview-url)
|
||||||
:title collectible-name
|
:title (:name collectible-data)
|
||||||
:description collection-name
|
:description (:name collection-data)
|
||||||
:theme theme}]
|
:theme theme}]
|
||||||
[reanimated/scroll-view
|
[reanimated/scroll-view
|
||||||
{:style (style/scroll-view top)
|
{:style (style/scroll-view top)
|
||||||
|
@ -13,25 +13,34 @@
|
|||||||
[{:keys [preview-url collection-data collectible-data total-owned on-press on-long-press]
|
[{:keys [preview-url collection-data collectible-data total-owned on-press on-long-press]
|
||||||
:as collectible}
|
:as collectible}
|
||||||
index]
|
index]
|
||||||
(let [on-press-fn (rn/use-callback #(when on-press
|
(let [gradient-color (keyword (str "gradient-" (inc (mod index 5))))
|
||||||
(on-press collectible %)))
|
on-press-fn (rn/use-callback
|
||||||
on-long-press-fn (rn/use-callback #(when on-long-press
|
(fn [aspect-ratio]
|
||||||
(on-long-press collectible)))]
|
(when (fn? on-press)
|
||||||
|
(on-press {:collectible (dissoc collectible :on-press :on-long-press)
|
||||||
|
:aspect-ratio aspect-ratio
|
||||||
|
:gradient-color gradient-color}))))
|
||||||
|
on-long-press-fn (rn/use-callback
|
||||||
|
(fn [aspect-ratio]
|
||||||
|
(when on-long-press
|
||||||
|
(on-long-press
|
||||||
|
(dissoc collectible :on-press :on-long-press)
|
||||||
|
aspect-ratio))))]
|
||||||
[quo/collectible-list-item
|
[quo/collectible-list-item
|
||||||
{:type :card
|
{:type :card
|
||||||
:image-src (:uri preview-url)
|
:image-src (:uri preview-url)
|
||||||
:avatar-image-src (:image-url collection-data)
|
:avatar-image-src (:image-url collection-data)
|
||||||
:collectible-name (:name collection-data)
|
:collectible-name (:name collectible-data)
|
||||||
:supported-file? (utils/supported-file? (:animation-media-type collectible-data))
|
:supported-file? (utils/supported-file? (:animation-media-type collectible-data))
|
||||||
:gradient-color-index (keyword (str "gradient-" (inc (mod index 5))))
|
:gradient-color-index gradient-color
|
||||||
:counter (utils/collectible-owned-counter total-owned)
|
:counter (utils/collectible-owned-counter total-owned)
|
||||||
:container-style style/collectible-container
|
:container-style style/collectible-container
|
||||||
:on-press on-press-fn
|
:on-press on-press-fn
|
||||||
:on-long-press on-long-press-fn}]))
|
:on-long-press on-long-press-fn}]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [collectibles filtered? on-end-reached
|
[{:keys [collectibles filtered? on-end-reached on-collectible-press
|
||||||
on-collectible-press current-account-address on-collectible-long-press]}]
|
current-account-address on-collectible-long-press]}]
|
||||||
(let [theme (quo.theme/use-theme)
|
(let [theme (quo.theme/use-theme)
|
||||||
no-results-match-query? (and filtered? (empty? collectibles))]
|
no-results-match-query? (and filtered? (empty? collectibles))]
|
||||||
(cond
|
(cond
|
||||||
|
@ -17,9 +17,7 @@
|
|||||||
:name (:name collectible-data)
|
:name (:name collectible-data)
|
||||||
:image (:uri preview-url)}])}]))
|
:image (:uri preview-url)}])}]))
|
||||||
|
|
||||||
(defn- on-collectible-press
|
(def on-collectible-press #(rf/dispatch [:wallet/navigate-to-collectible-details %]))
|
||||||
[{:keys [id]} aspect-ratio]
|
|
||||||
(rf/dispatch [:wallet/get-collectible-details id aspect-ratio]))
|
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [selected-tab]}]
|
[{:keys [selected-tab]}]
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
{:collectibles collectibles
|
{:collectibles collectibles
|
||||||
:filtered? search-performed?
|
:filtered? search-performed?
|
||||||
:on-end-reached #(rf/dispatch [:wallet/request-collectibles-for-current-viewing-account])
|
:on-end-reached #(rf/dispatch [:wallet/request-collectibles-for-current-viewing-account])
|
||||||
:on-collectible-press (fn [collectible]
|
:on-collectible-press (fn [{:keys [collectible]}]
|
||||||
(rf/dispatch [:wallet/set-collectible-to-send
|
(rf/dispatch [:wallet/set-collectible-to-send
|
||||||
{:collectible collectible
|
{:collectible collectible
|
||||||
:current-screen :screen/wallet.select-asset}]))}]))
|
:current-screen :screen/wallet.select-asset}]))}]))
|
||||||
|
@ -20,8 +20,7 @@
|
|||||||
(defn- preview-url
|
(defn- preview-url
|
||||||
[{{collectible-image-url :image-url
|
[{{collectible-image-url :image-url
|
||||||
animation-url :animation-url
|
animation-url :animation-url
|
||||||
animation-media-type :animation-media-type} :collectible-data
|
animation-media-type :animation-media-type} :collectible-data}]
|
||||||
{collection-image-url :image-url} :collection-data}]
|
|
||||||
(cond
|
(cond
|
||||||
(svg-animation? animation-url animation-media-type)
|
(svg-animation? animation-url animation-media-type)
|
||||||
{:uri animation-url
|
{:uri animation-url
|
||||||
@ -34,7 +33,7 @@
|
|||||||
{:uri collectible-image-url}
|
{:uri collectible-image-url}
|
||||||
|
|
||||||
:else
|
:else
|
||||||
{:uri collection-image-url}))
|
{:uri nil}))
|
||||||
|
|
||||||
(defn add-collectibles-preview-url
|
(defn add-collectibles-preview-url
|
||||||
[collectibles]
|
[collectibles]
|
||||||
@ -91,35 +90,36 @@
|
|||||||
current-account-collectibles))))
|
current-account-collectibles))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:wallet/last-collectible-details
|
:wallet/collectible
|
||||||
:<- [:wallet]
|
:<- [:wallet/ui]
|
||||||
(fn [wallet]
|
:-> :collectible)
|
||||||
(let [last-collectible (:last-collectible-details wallet)]
|
|
||||||
(assoc last-collectible :preview-url (preview-url last-collectible)))))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:wallet/last-collectible-aspect-ratio
|
:wallet/collectible-details
|
||||||
:<- [:wallet]
|
:<- [:wallet/collectible]
|
||||||
(fn [wallet]
|
|
||||||
(:last-collectible-aspect-ratio wallet)))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
|
||||||
:wallet/last-collectible-details-chain-id
|
|
||||||
:<- [:wallet/last-collectible-details]
|
|
||||||
(fn [collectible]
|
(fn [collectible]
|
||||||
(get-in collectible [:id :contract-id :chain-id])))
|
(as-> collectible $
|
||||||
|
(:details $)
|
||||||
|
(assoc $ :preview-url (preview-url $)))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:wallet/last-collectible-details-traits
|
:wallet/collectible-aspect-ratio
|
||||||
:<- [:wallet/last-collectible-details]
|
:<- [:wallet/collectible]
|
||||||
(fn [collectible]
|
(fn [collectible]
|
||||||
(get-in collectible [:collectible-data :traits])))
|
(:aspect-ratio collectible 1)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:wallet/last-collectible-details-owner
|
:wallet/collectible-gradient-color
|
||||||
:<- [:wallet/last-collectible-details]
|
:<- [:wallet/collectible]
|
||||||
:<- [:wallet]
|
(fn [collectible]
|
||||||
(fn [[collectible wallet]]
|
(:gradient-color collectible :gradient-1)))
|
||||||
(let [address (:address (first (:ownership collectible)))
|
|
||||||
account (get-in wallet [:accounts address])]
|
(re-frame/reg-sub
|
||||||
account)))
|
:wallet/collectible-details-owner
|
||||||
|
:<- [:wallet/accounts]
|
||||||
|
(fn [accounts [_ collectible]]
|
||||||
|
(let [collectible-address (-> collectible :ownership first :address)]
|
||||||
|
(some #(when (= (:address %) collectible-address)
|
||||||
|
%)
|
||||||
|
accounts))))
|
||||||
|
|
||||||
|
@ -2,49 +2,25 @@
|
|||||||
(:require
|
(:require
|
||||||
[cljs.test :refer [is testing]]
|
[cljs.test :refer [is testing]]
|
||||||
[re-frame.db :as rf-db]
|
[re-frame.db :as rf-db]
|
||||||
status-im.subs.root
|
[status-im.subs.root]
|
||||||
status-im.subs.wallet.collectibles
|
[status-im.subs.wallet.collectibles]
|
||||||
[test-helpers.unit :as h]
|
[test-helpers.unit :as h]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(def ^:private traits
|
(def collectible-owner-wallet
|
||||||
[{:trait-type "Background"
|
{:ui {:collectible {:details {:ownership [{:address "0x1"}]}}}
|
||||||
:value "Gradient 5"
|
:accounts {"0x1" {:address "0x1"
|
||||||
:display-type ""
|
:name "account 1"
|
||||||
:max-value ""}
|
:color "army"}}})
|
||||||
{:trait-type "Skin"
|
|
||||||
:value "Pale"
|
|
||||||
:display-type ""
|
|
||||||
:max-value ""}
|
|
||||||
{:trait-type "Clothes"
|
|
||||||
:value "Naked"
|
|
||||||
:display-type ""
|
|
||||||
:max-value ""}])
|
|
||||||
|
|
||||||
(def ^:private collectible-owner-wallet
|
(h/deftest-sub :wallet/collectible-details-owner
|
||||||
{: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]
|
[sub-name]
|
||||||
(testing "correct owner of the last collectible should be returned"
|
(testing "correct owner of the last collectible should be returned"
|
||||||
(swap! rf-db/app-db assoc-in [:wallet] collectible-owner-wallet)
|
(swap! rf-db/app-db assoc :wallet collectible-owner-wallet)
|
||||||
(let [result (rf/sub [sub-name])]
|
(let [collectible (-> collectible-owner-wallet :ui :collectible :details)
|
||||||
(is (= {:name "account 1"
|
result (rf/sub [sub-name collectible])]
|
||||||
:color "army"}
|
(is (= {:name "account 1"
|
||||||
|
:color "army"
|
||||||
|
:address "0x1"
|
||||||
|
:network-preferences-names #{}}
|
||||||
result)))))
|
result)))))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user