fast image loading indicator (#13431)

* fast image loading indicator
This commit is contained in:
flexsurfer 2022-06-03 13:37:27 +02:00 committed by GitHub
parent b18547c16e
commit 5b7d0f81d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 84 additions and 41 deletions

View File

@ -0,0 +1,29 @@
(ns status-im.ui.components.fast-image
(:require [reagent.core :as reagent]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.react :as react]))
(defn placeholder [style child]
[react/view {:style (merge style {:flex 1 :justify-content :center :align-items :center})}
child])
(defn fast-image [_]
(let [loaded? (reagent/atom false)
error? (reagent/atom false)]
(fn [props]
[react/fast-image-class (merge
props
{:on-error (fn [e]
(when-let [on-error (:on-error props)]
(on-error e))
(reset! error? true))
:on-load (fn [e]
(when-let [on-load (:on-load props)]
(on-load e))
(reset! loaded? true))})
(when (or @error? (not @loaded?))
[placeholder (:style props)
(if @error?
[icons/icon :main-icons/cancel]
(when-not @loaded?
[react/activity-indicator {:animating true}]))])])))

View File

@ -33,7 +33,7 @@
(def image-class (reagent/adapt-react-class (reactjs/memo (.-Image react-native))))
(def fast-image (reagent/adapt-react-class FastImage))
(def fast-image-class (reagent/adapt-react-class FastImage))
(defn image-get-size [uri callback] (.getSize (.-Image react-native) uri callback))
(defn resolve-asset-source [uri] (js->clj (.resolveAssetSource (.-Image react-native) uri) :keywordize-keys true))

View File

@ -25,7 +25,8 @@
[status-im.ui.screens.communities.icon :as communities.icon]
[status-im.ui.components.animation :as animation]
[status-im.chat.models.images :as images]
[status-im.chat.models.pin-message :as models.pin-message])
[status-im.chat.models.pin-message :as models.pin-message]
[status-im.ui.components.fast-image :as fast-image])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn message-timestamp-anim
@ -99,11 +100,11 @@
(if (and image
;; Disabling images for public-chats
(not public?))
[react/fast-image {:style {:width 56
:height 56
:background-color :black
:border-radius 4}
:source {:uri image}}]
[fast-image/fast-image {:style {:width 56
:height 56
:background-color :black
:border-radius 4}
:source {:uri image}}]
[react/text {:style (style/quoted-message-text (and outgoing (not pinned)))
:number-of-lines 5}
(components.reply/get-quoted-text-with-mentions parsed-text)])]))
@ -374,9 +375,17 @@
:disabled in-popover?}
[react/view {:style (style/image-message style-opts)
:accessibility-label :image-message}
[react/fast-image {:style (dissoc style-opts :outgoing)
:on-load (image-set-size dimensions)
:source {:uri uri}}]
(when (or (:error @dimensions) (not (:loaded @dimensions)))
[react/view
(merge (dissoc style-opts :opacity)
{:flex 1 :align-items :center :justify-content :center :position :absolute})
(if (:error @dimensions)
[icons/icon :main-icons/cancel]
[react/activity-indicator {:animating true}])])
[fast-image/fast-image {:style (dissoc style-opts :outgoing)
:on-load (image-set-size dimensions)
:on-error #(swap! dimensions assoc :error true)
:source {:uri uri}}]
[react/view {:style (style/image-message-border style-opts)}]]]]))))
(defmulti ->message :content-type)
@ -567,8 +576,8 @@
[{:on-press #(when pack
(re-frame/dispatch [:chat.ui/show-profile from]))
:label (i18n/label :t/view-details)}])))})
[react/fast-image {:style {:margin 10 :width 140 :height 140}
:source {:uri (str (-> content :sticker :url) "&download=true")}}]]
[fast-image/fast-image {:style {:margin 10 :width 140 :height 140}
:source {:uri (str (-> content :sticker :url) "&download=true")}}]]
reaction-picker]))
(defmethod ->message constants/content-type-image

View File

@ -5,16 +5,17 @@
[status-im.profile.db :as profile.db]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.image :as utils.image]
[quo.design-system.colors :as colors]))
[quo.design-system.colors :as colors]
[status-im.ui.components.fast-image :as fast-image]))
(def memo-photo-rend
(memoize
(fn [photo-path size accessibility-label _]
(let [identicon? (when photo-path (profile.db/base64-png? photo-path))]
[react/view {:style (style/photo-container size)}
[react/fast-image {:source (utils.image/source photo-path)
:style (style/photo size)
:accessibility-label (or accessibility-label :chat-icon)}]
[fast-image/fast-image {:source (utils.image/source photo-path)
:style (style/photo size)
:accessibility-label (or accessibility-label :chat-icon)}]
(when identicon?
[react/view {:style (style/photo-border size)}])]))))
@ -36,7 +37,7 @@
(defn member-identicon [identicon]
(let [size style/default-size]
[react/view {:style (style/photo-container size)}
[react/fast-image {:source {:uri identicon}
:style (style/photo size)
:accessibility-label :member-photo}]
[fast-image/fast-image {:source {:uri identicon}
:style (style/photo size)
:accessibility-label :member-photo}]
[react/view {:style (style/photo-border size)}]]))

View File

@ -8,7 +8,8 @@
[status-im.i18n.i18n :as i18n]
[quo.core :as quo]
[status-im.ui.screens.chat.stickers.styles :as styles]
[status-im.utils.debounce :as debounce]))
[status-im.utils.debounce :as debounce]
[status-im.ui.components.fast-image :as fast-image]))
(def icon-size 28)
(def icon-horizontal-margin 8)
@ -35,9 +36,9 @@
^{:key (str url)}
[react/touchable-highlight {:style {:height 75 :width 75 :margin 5}
:on-press #(debounce/dispatch-and-chill [:chat/send-sticker sticker] 1000)}
[react/fast-image {:style {:width "100%" :height "100%"}
:accessibility-label :sticker-icon
:source {:uri (str url "&download=true")}}]])]]])
[fast-image/fast-image {:style {:width "100%" :height "100%"}
:accessibility-label :sticker-icon
:source {:uri (str url "&download=true")}}]])]]])
(defview recent-stickers-panel [window-width]
(letsubs [stickers [:stickers/recent-stickers]]
@ -137,6 +138,6 @@
^{:key (str "pack-icon" id)}
[pack-icon {:id id
:background-color colors/white}
[react/fast-image {:style {:width icon-size :height icon-size :border-radius (/ icon-size 2)}
:source {:uri (str thumbnail "&download=true")}}]])]
[fast-image/fast-image {:style {:width icon-size :height icon-size :border-radius (/ icon-size 2)}
:source {:uri (str thumbnail "&download=true")}}]])]
[scroll-indicator]]]]]))

View File

@ -400,7 +400,8 @@
(defn image-message-border [opts]
(merge (image-message opts)
{:border-width 1
{:opacity (:opacity opts)
:border-width 1
:top 0
:left 0
:position :absolute

View File

@ -19,7 +19,8 @@
[status-im.chat.models.reactions :as models.reactions]
[status-im.ui.screens.chat.components.reply :as components.reply]
[status-im.ui.screens.chat.message.link-preview :as link-preview]
[status-im.chat.models :as chat]))
[status-im.chat.models :as chat]
[status-im.ui.components.fast-image :as fast-image]))
(defonce messages-list-ref (atom nil))
(def image-max-dimension 192)
@ -40,10 +41,10 @@
:border-radius 16
:margin-top 8}
:accessibility-label :image-message}
[react/fast-image {:style {:width @width
:height image-max-dimension}
:on-load (image-set-size width)
:source {:uri uri}}]
[fast-image/fast-image {:style {:width @width
:height image-max-dimension}
:on-load (image-set-size width)
:source {:uri uri}}]
[react/view {:border-width 1
:top 0
:left 0
@ -188,10 +189,10 @@
(if no-messages?
[react/view {:padding-horizontal 32
:margin-top 64}
[react/fast-image {:style {:width 140
:height 140
:align-self :center}
:source {:uri "https://bafybeieayj76s4vjlw5uwdvnakosy46rqyioqsp2ygl6sedivemhkxrbwi.ipfs.cf-ipfs.com"}}]
[fast-image/fast-image {:style {:width 140
:height 140
:align-self :center}
:source {:uri "https://bafybeieayj76s4vjlw5uwdvnakosy46rqyioqsp2ygl6sedivemhkxrbwi.ipfs.cf-ipfs.com"}}]
[react/view (styles/descr-container)
[react/text {:style {:color colors/gray
:line-height 22}}

View File

@ -6,15 +6,16 @@
[status-im.ui.components.react :as react]
[status-im.ui.screens.stickers.styles :as styles]
[status-im.utils.money :as money]
[status-im.utils.handlers :refer [<sub]])
[status-im.utils.handlers :refer [<sub]]
[status-im.ui.components.fast-image :as fast-image])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn cache [url]
(str url "&download=true"))
(defn- thumbnail-icon [uri size]
[react/fast-image {:style {:width size :height size :border-radius (/ size 2)}
:source {:uri (cache uri)}}])
[fast-image/fast-image {:style {:width size :height size :border-radius (/ size 2)}
:source {:uri (cache uri)}}])
(defn price-badge [_]
(let [chain (<sub [:ethereum/chain-keyword])
@ -47,7 +48,7 @@
(defn pack-badge [{:keys [name author thumbnail preview id] :as pack}]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :stickers-pack {:id id}])}
[react/view {:margin-bottom 27}
[react/fast-image {:style {:height 200 :border-radius 20} :source {:uri (cache preview)}}]
[fast-image/fast-image {:style {:height 200 :border-radius 20} :source {:uri (cache preview)}}]
[react/view {:height 64 :align-items :center :flex-direction :row}
[thumbnail-icon thumbnail 40]
[react/view {:padding-horizontal 16 :flex 1}
@ -89,8 +90,8 @@
[react/view {:flex-direction :row :flex-wrap :wrap}
(for [{:keys [url]} stickers]
^{:key url}
[react/fast-image {:style (styles/sticker-image sticker-icon-size)
:source {:uri (cache url)}}])]]]]
[fast-image/fast-image {:style (styles/sticker-image sticker-icon-size)
:source {:uri (cache url)}}])]]]]
[react/view {:flex 1 :align-items :center :justify-content :center}
[react/activity-indicator {:animating true}]])]))