feat: collectibles details loading (#20400)

This commit is contained in:
BalogunofAfrica 2024-07-03 15:49:12 +01:00 committed by GitHub
parent b28a8e153e
commit b17f2892c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 152 additions and 57 deletions

View File

@ -34,6 +34,12 @@
(set-state (fn [prev-state]
(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
[set-state]
(js/setTimeout (fn []
@ -147,6 +153,7 @@
[reanimated/view {:style (style/supported-file image-opacity)}
[rn/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-end #(on-load-end {:load-time load-time
:set-state set-state
@ -197,6 +204,7 @@
[reanimated/view {:style (style/supported-file image-opacity)}
[rn/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-end #(on-load-end {:load-time load-time
:set-state set-state
@ -219,12 +227,13 @@
(defn- view-internal
[{:keys [container-style type on-press on-long-press supported-file?]
:as props}]
(let [[state set-state] (rn/use-state {:image-loaded? false
:image-error? false
:avatar-loaded? false})
(let [[state set-state] (rn/use-state {:image-loaded? false
:image-aspect-ratio nil
:image-error? false
:avatar-loaded? false})
collectible-ready? (or (:image-loaded? state) (not supported-file?))]
[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)
:accessibility-label :collectible-list-item
:style container-style}

View File

@ -1,10 +1,13 @@
(ns quo.components.profile.expanded-collectible.style
(:require [quo.foundations.colors :as colors]))
(def container
{:align-items :center
:justify-content :center
:border-radius 16})
(defn container
[aspect-ratio]
(cond-> {:align-items :center
:justify-content :center
:border-radius 16}
aspect-ratio (assoc :width "100%"
:aspect-ratio aspect-ratio)))
(defn image
[square? aspect-ratio theme]
@ -25,18 +28,43 @@
:border-color (colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme)})
(defn fallback
[{:keys [theme]}]
{:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
:border-style :dashed
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
:border-width 1
:border-radius 16
:width "100%"
:aspect-ratio 1
:align-items :center
:justify-content :center})
([theme]
(fallback theme 1))
([theme aspect-ratio]
{:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
:border-style :dashed
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
:border-width 1
:border-radius 16
:width "100%"
:aspect-ratio aspect-ratio
:align-items :center
:justify-content :center}))
(def counter
{:position :absolute
:top 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})

View File

@ -1,17 +1,53 @@
(ns quo.components.profile.expanded-collectible.view
(:require
[clojure.string :as string]
[promesa.core :as promesa]
[quo.components.counter.collectible-counter.view :as collectible-counter]
[quo.components.icon :as icon]
[quo.components.markdown.text :as text]
[quo.components.profile.expanded-collectible.style :as style]
[quo.foundations.colors :as colors]
[quo.foundations.gradients :as gradients]
[quo.theme]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[schema.core :as schema]
[utils.datetime :as datetime]
[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
[counter]
[collectible-counter/view
@ -21,7 +57,7 @@
(defn- fallback-view
[{:keys [label theme counter on-mount]}]
(rn/use-mount on-mount)
[rn/view {:style (style/fallback {:theme theme})}
[rn/view {:style (style/fallback theme)}
[counter-view counter]
[rn/view
[icon/icon :i/sad {:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}]]
@ -33,45 +69,57 @@
(defn view-internal
[{:keys [container-style square? on-press counter image-src native-ID supported-file?
on-collectible-load]}]
(let [theme (quo.theme/use-theme)
[image-size set-image-size] (rn/use-state {})
[image-error? set-image-error] (rn/use-state (or (nil? image-src)
(string/blank? image-src)))]
(rn/use-effect
(fn []
(promesa/let [[image-width image-height] (rn/image-get-size image-src)]
(set-image-size {:width image-width
:height image-height
:aspect-ratio (/ image-width image-height)})))
[image-src])
on-collectible-load aspect-ratio]}]
(let [theme (quo.theme/use-theme)
loader-opacity (reanimated/use-shared-value
(if supported-file? 1 0))
image-opacity (reanimated/use-shared-value
(if supported-file? 0 1))
[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
{: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
:style (merge container-style style/container)}
:style (merge container-style
(style/container aspect-ratio))}
(cond
(not supported-file?)
[fallback-view
{:label (i18n/label :t/unsupported-file)
:counter counter
:theme theme
:on-mount on-collectible-load}]
{:aspect-ratio aspect-ratio
:label (i18n/label :t/unsupported-file)
:counter counter
:theme theme
:on-mount on-collectible-load}]
image-error?
(:image-error? state)
[fallback-view
{:label (i18n/label :t/cant-fetch-info)
:counter counter
:theme theme
:on-mount on-collectible-load}]
:else
[rn/view
(not (:image-loaded? state))
[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
{:style (style/image square? (:aspect-ratio image-size) theme)
:source image-src
:native-ID native-ID
:on-error #(set-image-error true)
:on-load on-collectible-load}]
{:style (style/image square? aspect-ratio theme)
:source image-src
:native-ID native-ID
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
: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)}]])]))
@ -81,6 +129,7 @@
[:catn
[:props
[:map {:closed true}
[:aspect-ratio {:optional true} [:maybe number?]]
[:image-src {:optional true} [:maybe string?]]
[:supported-file? {:optional true} [:maybe boolean?]]
[:container-style {:optional true} [:maybe :map]]

View File

@ -12,8 +12,8 @@
[utils.re-frame :as rf]))
(defn- on-collectible-press
[{:keys [id]}]
(rf/dispatch [:wallet/get-collectible-details id]))
[{:keys [id]} aspect-ratio]
(rf/dispatch [:wallet/get-collectible-details id aspect-ratio]))
(defn- on-collectible-long-press
[{:keys [preview-url collectible-details id]}]

View File

@ -167,12 +167,13 @@
(rf/reg-event-fx
:wallet/get-collectible-details
(fn [_ [collectible-id]]
(fn [{:keys [db]} [collectible-id aspect-ratio]]
(let [request-id 0
collectible-id-converted (cske/transform-keys transforms/->PascalCaseKeyword collectible-id)
data-type (collectible-data-types :details)
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"
:params request-params
:on-error (fn [error]
@ -197,7 +198,7 @@
(rf/reg-event-fx
:wallet/clear-last-collectible-details
(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
(fn [_ [{:keys [title uri]}]]

View File

@ -12,8 +12,8 @@
(defn preview-container
[]
{:margin-horizontal 8
:margin-top (+ (header-height) 12)})
{:padding-horizontal 8
:margin-top (+ (header-height) 12)})
(def header
{:margin-horizontal 20

View File

@ -150,6 +150,7 @@
set-title-ref (rn/use-callback #(reset! title-ref %))
animation-shared-element-id (rf/sub [:animation-shared-element-id])
collectible-owner (rf/sub [:wallet/last-collectible-details-owner])
aspect-ratio (rf/sub [:wallet/last-collectible-aspect-ratio])
{:keys [id
preview-url
collection-data
@ -180,7 +181,8 @@
[rn/view
[gradient-layer preview-uri]
[quo/expanded-collectible
{:image-src preview-uri
{:aspect-ratio aspect-ratio
:image-src preview-uri
:container-style (style/preview-container)
:counter (utils/collectible-owned-counter total-owned)
:native-ID (when (= animation-shared-element-id token-id) :shared-element)

View File

@ -14,7 +14,7 @@
:as collectible}
index]
(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 collectible)))]
[quo/collectible-list-item

View File

@ -18,8 +18,8 @@
:image (:uri preview-url)}])}]))
(defn- on-collectible-press
[{:keys [id]}]
(rf/dispatch [:wallet/get-collectible-details id]))
[{:keys [id]} aspect-ratio]
(rf/dispatch [:wallet/get-collectible-details id aspect-ratio]))
(defn view
[{:keys [selected-tab]}]

View File

@ -97,6 +97,12 @@
(let [last-collectible (:last-collectible-details wallet)]
(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
:wallet/last-collectible-details-chain-id
:<- [:wallet/last-collectible-details]