feat: collectibles details loading (#20400)
This commit is contained in:
parent
b28a8e153e
commit
b17f2892c7
|
@ -34,6 +34,12 @@
|
||||||
(set-state (fn [prev-state]
|
(set-state (fn [prev-state]
|
||||||
(assoc prev-state :image-loaded? true)))))
|
(assoc prev-state :image-loaded? true)))))
|
||||||
|
|
||||||
|
(defn on-load
|
||||||
|
[evt set-state]
|
||||||
|
(let [source (.. evt -nativeEvent -source)
|
||||||
|
aspect-ratio (/ (.-width source) (.-height source))]
|
||||||
|
(set-state (fn [prev-state] (assoc prev-state :image-aspect-ratio aspect-ratio)))))
|
||||||
|
|
||||||
(defn on-load-error
|
(defn on-load-error
|
||||||
[set-state]
|
[set-state]
|
||||||
(js/setTimeout (fn []
|
(js/setTimeout (fn []
|
||||||
|
@ -147,6 +153,7 @@
|
||||||
[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-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 #(on-load-end {:load-time load-time
|
||||||
:set-state set-state
|
:set-state set-state
|
||||||
|
@ -197,6 +204,7 @@
|
||||||
[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-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 #(on-load-end {:load-time load-time
|
||||||
:set-state set-state
|
:set-state set-state
|
||||||
|
@ -219,12 +227,13 @@
|
||||||
(defn- view-internal
|
(defn- view-internal
|
||||||
[{:keys [container-style type on-press on-long-press supported-file?]
|
[{:keys [container-style type on-press on-long-press supported-file?]
|
||||||
:as props}]
|
:as props}]
|
||||||
(let [[state set-state] (rn/use-state {:image-loaded? false
|
(let [[state set-state] (rn/use-state {:image-loaded? false
|
||||||
:image-error? false
|
:image-aspect-ratio nil
|
||||||
:avatar-loaded? false})
|
:image-error? false
|
||||||
|
:avatar-loaded? false})
|
||||||
collectible-ready? (or (:image-loaded? state) (not supported-file?))]
|
collectible-ready? (or (:image-loaded? state) (not supported-file?))]
|
||||||
[rn/pressable
|
[rn/pressable
|
||||||
{:on-press (when collectible-ready? on-press)
|
{:on-press (when collectible-ready? #(on-press (:image-aspect-ratio state)))
|
||||||
:on-long-press (when collectible-ready? on-long-press)
|
:on-long-press (when collectible-ready? on-long-press)
|
||||||
:accessibility-label :collectible-list-item
|
:accessibility-label :collectible-list-item
|
||||||
:style container-style}
|
:style container-style}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
(ns quo.components.profile.expanded-collectible.style
|
(ns quo.components.profile.expanded-collectible.style
|
||||||
(:require [quo.foundations.colors :as colors]))
|
(:require [quo.foundations.colors :as colors]))
|
||||||
|
|
||||||
(def container
|
(defn container
|
||||||
{:align-items :center
|
[aspect-ratio]
|
||||||
:justify-content :center
|
(cond-> {:align-items :center
|
||||||
:border-radius 16})
|
:justify-content :center
|
||||||
|
:border-radius 16}
|
||||||
|
aspect-ratio (assoc :width "100%"
|
||||||
|
:aspect-ratio aspect-ratio)))
|
||||||
|
|
||||||
(defn image
|
(defn image
|
||||||
[square? aspect-ratio theme]
|
[square? aspect-ratio theme]
|
||||||
|
@ -25,18 +28,43 @@
|
||||||
:border-color (colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme)})
|
:border-color (colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme)})
|
||||||
|
|
||||||
(defn fallback
|
(defn fallback
|
||||||
[{:keys [theme]}]
|
([theme]
|
||||||
{:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
|
(fallback theme 1))
|
||||||
:border-style :dashed
|
([theme aspect-ratio]
|
||||||
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
|
{:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
|
||||||
:border-width 1
|
:border-style :dashed
|
||||||
:border-radius 16
|
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
|
||||||
:width "100%"
|
:border-width 1
|
||||||
:aspect-ratio 1
|
:border-radius 16
|
||||||
:align-items :center
|
:width "100%"
|
||||||
:justify-content :center})
|
:aspect-ratio aspect-ratio
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center}))
|
||||||
|
|
||||||
(def counter
|
(def counter
|
||||||
{:position :absolute
|
{:position :absolute
|
||||||
:top 12
|
:top 12
|
||||||
:right 12})
|
:right 12})
|
||||||
|
|
||||||
|
(defn loading-image-with-opacity
|
||||||
|
[opacity]
|
||||||
|
[{:align-items :center
|
||||||
|
:aspect-ratio 1
|
||||||
|
:border-radius 16
|
||||||
|
:justify-content :center
|
||||||
|
:opacity opacity
|
||||||
|
:position :absolute
|
||||||
|
:width "100%"
|
||||||
|
:z-index 1}])
|
||||||
|
|
||||||
|
(defn gradient-view
|
||||||
|
[aspect-ratio]
|
||||||
|
{:border-radius 16
|
||||||
|
:width "100%"
|
||||||
|
:aspect-ratio aspect-ratio
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center})
|
||||||
|
|
||||||
|
(defn supported-file
|
||||||
|
[opacity]
|
||||||
|
{:opacity opacity})
|
||||||
|
|
|
@ -1,17 +1,53 @@
|
||||||
(ns quo.components.profile.expanded-collectible.view
|
(ns quo.components.profile.expanded-collectible.view
|
||||||
(:require
|
(:require
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[promesa.core :as promesa]
|
|
||||||
[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]
|
||||||
[quo.components.markdown.text :as text]
|
[quo.components.markdown.text :as text]
|
||||||
[quo.components.profile.expanded-collectible.style :as style]
|
[quo.components.profile.expanded-collectible.style :as style]
|
||||||
[quo.foundations.colors :as colors]
|
[quo.foundations.colors :as colors]
|
||||||
|
[quo.foundations.gradients :as gradients]
|
||||||
[quo.theme]
|
[quo.theme]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
|
[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 timing-options-in 1000)
|
||||||
|
(def first-load-time 500)
|
||||||
|
(def cached-load-time 200)
|
||||||
|
(def error-wait-time 800)
|
||||||
|
|
||||||
|
(defn on-load-end
|
||||||
|
[{:keys [load-time set-state loader-opacity image-opacity]}]
|
||||||
|
(reanimated/animate loader-opacity 0 timing-options-out)
|
||||||
|
(reanimated/animate image-opacity 1 timing-options-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
|
||||||
|
[set-state]
|
||||||
|
(js/setTimeout (fn []
|
||||||
|
(set-state (fn [prev-state] (assoc prev-state :image-error? true))))
|
||||||
|
error-wait-time))
|
||||||
|
|
||||||
|
(defn- loading-image
|
||||||
|
[{:keys [theme gradient-color-index loader-opacity aspect-ratio]}]
|
||||||
|
[reanimated/view
|
||||||
|
{:style (style/loading-image-with-opacity loader-opacity)}
|
||||||
|
[gradients/view
|
||||||
|
{:theme theme
|
||||||
|
:container-style (style/gradient-view aspect-ratio)
|
||||||
|
:color-index gradient-color-index}]])
|
||||||
|
|
||||||
(defn- counter-view
|
(defn- counter-view
|
||||||
[counter]
|
[counter]
|
||||||
[collectible-counter/view
|
[collectible-counter/view
|
||||||
|
@ -21,7 +57,7 @@
|
||||||
(defn- fallback-view
|
(defn- fallback-view
|
||||||
[{:keys [label theme counter on-mount]}]
|
[{:keys [label theme counter on-mount]}]
|
||||||
(rn/use-mount on-mount)
|
(rn/use-mount on-mount)
|
||||||
[rn/view {:style (style/fallback {:theme theme})}
|
[rn/view {:style (style/fallback theme)}
|
||||||
[counter-view counter]
|
[counter-view counter]
|
||||||
[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)}]]
|
||||||
|
@ -33,45 +69,57 @@
|
||||||
|
|
||||||
(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]}]
|
on-collectible-load aspect-ratio]}]
|
||||||
(let [theme (quo.theme/use-theme)
|
(let [theme (quo.theme/use-theme)
|
||||||
[image-size set-image-size] (rn/use-state {})
|
loader-opacity (reanimated/use-shared-value
|
||||||
[image-error? set-image-error] (rn/use-state (or (nil? image-src)
|
(if supported-file? 1 0))
|
||||||
(string/blank? image-src)))]
|
image-opacity (reanimated/use-shared-value
|
||||||
(rn/use-effect
|
(if supported-file? 0 1))
|
||||||
(fn []
|
[load-time set-load-time] (rn/use-state (datetime/now))
|
||||||
(promesa/let [[image-width image-height] (rn/image-get-size image-src)]
|
[state set-state] (rn/use-state {:image-loaded? false
|
||||||
(set-image-size {:width image-width
|
:image-error? (or (nil? image-src)
|
||||||
:height image-height
|
(string/blank?
|
||||||
:aspect-ratio (/ image-width image-height)})))
|
image-src))})]
|
||||||
[image-src])
|
|
||||||
[rn/pressable
|
[rn/pressable
|
||||||
{:on-press (when (and (not image-error?) supported-file?) on-press)
|
{:on-press (when (and (not (:image-error? state)) supported-file?) on-press)
|
||||||
:accessibility-label :expanded-collectible
|
:accessibility-label :expanded-collectible
|
||||||
:style (merge container-style style/container)}
|
:style (merge container-style
|
||||||
|
(style/container aspect-ratio))}
|
||||||
(cond
|
(cond
|
||||||
(not supported-file?)
|
(not supported-file?)
|
||||||
[fallback-view
|
[fallback-view
|
||||||
{:label (i18n/label :t/unsupported-file)
|
{:aspect-ratio aspect-ratio
|
||||||
:counter counter
|
:label (i18n/label :t/unsupported-file)
|
||||||
:theme theme
|
:counter counter
|
||||||
:on-mount on-collectible-load}]
|
:theme theme
|
||||||
|
:on-mount on-collectible-load}]
|
||||||
|
|
||||||
image-error?
|
(:image-error? state)
|
||||||
[fallback-view
|
[fallback-view
|
||||||
{:label (i18n/label :t/cant-fetch-info)
|
{: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}]
|
||||||
|
|
||||||
:else
|
(not (:image-loaded? state))
|
||||||
[rn/view
|
[loading-image
|
||||||
|
{:aspect-ratio aspect-ratio
|
||||||
|
:loader-opacity loader-opacity
|
||||||
|
:theme theme
|
||||||
|
:gradient-color-index :gradient-5}])
|
||||||
|
(when supported-file?
|
||||||
|
[reanimated/view {:style (style/supported-file image-opacity)}
|
||||||
[rn/image
|
[rn/image
|
||||||
{:style (style/image square? (:aspect-ratio image-size) theme)
|
{:style (style/image square? aspect-ratio theme)
|
||||||
:source image-src
|
:source image-src
|
||||||
:native-ID native-ID
|
:native-ID native-ID
|
||||||
:on-error #(set-image-error true)
|
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
||||||
:on-load on-collectible-load}]
|
: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
|
(when counter
|
||||||
[counter-view counter])
|
[counter-view counter])
|
||||||
[rn/view {:style (style/collectible-border theme)}]])]))
|
[rn/view {:style (style/collectible-border theme)}]])]))
|
||||||
|
@ -81,6 +129,7 @@
|
||||||
[:catn
|
[:catn
|
||||||
[:props
|
[:props
|
||||||
[:map {:closed true}
|
[:map {:closed true}
|
||||||
|
[:aspect-ratio {:optional true} [:maybe number?]]
|
||||||
[:image-src {:optional true} [:maybe string?]]
|
[:image-src {:optional true} [:maybe string?]]
|
||||||
[:supported-file? {:optional true} [:maybe boolean?]]
|
[:supported-file? {:optional true} [:maybe boolean?]]
|
||||||
[:container-style {:optional true} [:maybe :map]]
|
[:container-style {:optional true} [:maybe :map]]
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn- on-collectible-press
|
(defn- on-collectible-press
|
||||||
[{:keys [id]}]
|
[{:keys [id]} aspect-ratio]
|
||||||
(rf/dispatch [:wallet/get-collectible-details id]))
|
(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]}]
|
||||||
|
|
|
@ -167,12 +167,13 @@
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet/get-collectible-details
|
:wallet/get-collectible-details
|
||||||
(fn [_ [collectible-id]]
|
(fn [{:keys [db]} [collectible-id aspect-ratio]]
|
||||||
(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]]
|
||||||
{:fx [[:json-rpc/call
|
{:db (assoc-in db [:wallet :last-collectible-aspect-ratio] aspect-ratio)
|
||||||
|
:fx [[:json-rpc/call
|
||||||
[{:method "wallet_getCollectiblesByUniqueIDAsync"
|
[{:method "wallet_getCollectiblesByUniqueIDAsync"
|
||||||
:params request-params
|
:params request-params
|
||||||
:on-error (fn [error]
|
:on-error (fn [error]
|
||||||
|
@ -197,7 +198,7 @@
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet/clear-last-collectible-details
|
:wallet/clear-last-collectible-details
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
{:db (update-in db [:wallet] dissoc :last-collectible-details)}))
|
{:db (update-in db [:wallet] dissoc :last-collectible-details :last-collectible-aspect-ratio)}))
|
||||||
|
|
||||||
(rf/reg-event-fx :wallet/trigger-share-collectible
|
(rf/reg-event-fx :wallet/trigger-share-collectible
|
||||||
(fn [_ [{:keys [title uri]}]]
|
(fn [_ [{:keys [title uri]}]]
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
|
|
||||||
(defn preview-container
|
(defn preview-container
|
||||||
[]
|
[]
|
||||||
{:margin-horizontal 8
|
{:padding-horizontal 8
|
||||||
:margin-top (+ (header-height) 12)})
|
:margin-top (+ (header-height) 12)})
|
||||||
|
|
||||||
(def header
|
(def header
|
||||||
{:margin-horizontal 20
|
{:margin-horizontal 20
|
||||||
|
|
|
@ -150,6 +150,7 @@
|
||||||
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/last-collectible-details-owner])
|
||||||
|
aspect-ratio (rf/sub [:wallet/last-collectible-aspect-ratio])
|
||||||
{:keys [id
|
{:keys [id
|
||||||
preview-url
|
preview-url
|
||||||
collection-data
|
collection-data
|
||||||
|
@ -180,7 +181,8 @@
|
||||||
[rn/view
|
[rn/view
|
||||||
[gradient-layer preview-uri]
|
[gradient-layer preview-uri]
|
||||||
[quo/expanded-collectible
|
[quo/expanded-collectible
|
||||||
{:image-src preview-uri
|
{:aspect-ratio aspect-ratio
|
||||||
|
:image-src preview-uri
|
||||||
:container-style (style/preview-container)
|
:container-style (style/preview-container)
|
||||||
:counter (utils/collectible-owned-counter total-owned)
|
:counter (utils/collectible-owned-counter total-owned)
|
||||||
:native-ID (when (= animation-shared-element-id token-id) :shared-element)
|
:native-ID (when (= animation-shared-element-id token-id) :shared-element)
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
:as collectible}
|
:as collectible}
|
||||||
index]
|
index]
|
||||||
(let [on-press-fn (rn/use-callback #(when on-press
|
(let [on-press-fn (rn/use-callback #(when on-press
|
||||||
(on-press collectible)))
|
(on-press collectible %)))
|
||||||
on-long-press-fn (rn/use-callback #(when on-long-press
|
on-long-press-fn (rn/use-callback #(when on-long-press
|
||||||
(on-long-press collectible)))]
|
(on-long-press collectible)))]
|
||||||
[quo/collectible-list-item
|
[quo/collectible-list-item
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
:image (:uri preview-url)}])}]))
|
:image (:uri preview-url)}])}]))
|
||||||
|
|
||||||
(defn- on-collectible-press
|
(defn- on-collectible-press
|
||||||
[{:keys [id]}]
|
[{:keys [id]} aspect-ratio]
|
||||||
(rf/dispatch [:wallet/get-collectible-details id]))
|
(rf/dispatch [:wallet/get-collectible-details id aspect-ratio]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [selected-tab]}]
|
[{:keys [selected-tab]}]
|
||||||
|
|
|
@ -97,6 +97,12 @@
|
||||||
(let [last-collectible (:last-collectible-details wallet)]
|
(let [last-collectible (:last-collectible-details wallet)]
|
||||||
(assoc last-collectible :preview-url (preview-url last-collectible)))))
|
(assoc last-collectible :preview-url (preview-url last-collectible)))))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:wallet/last-collectible-aspect-ratio
|
||||||
|
:<- [:wallet]
|
||||||
|
(fn [wallet]
|
||||||
|
(:last-collectible-aspect-ratio wallet)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:wallet/last-collectible-details-chain-id
|
:wallet/last-collectible-details-chain-id
|
||||||
:<- [:wallet/last-collectible-details]
|
:<- [:wallet/last-collectible-details]
|
||||||
|
|
Loading…
Reference in New Issue