Implement new URL Preview component (#15607)

Fix https://github.com/status-im/status-mobile/issues/15592

Notes:

- The red border around the icon has been reported in issue
  https://github.com/status-im/status-mobile/issues/15606
- The loading state doesn't have a spinning icon on purpose. This will be done
  separately.
This commit is contained in:
Icaro Motta 2023-04-10 22:02:39 -03:00 committed by GitHub
parent ccb20d7994
commit bfc7a2d88b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 241 additions and 25 deletions

View File

@ -0,0 +1,29 @@
(ns quo2.components.links.url-preview.component-spec
(:require
[quo2.components.links.url-preview.view :as view]
[test-helpers.component :as h]))
(h/describe "Links - URL Preview"
(h/test "default render"
(h/render [view/view])
(h/is-truthy (h/query-by-label-text :title))
(h/is-truthy (h/query-by-label-text :logo))
(h/is-truthy (h/query-by-label-text :button-clear-preview))
(h/is-null (h/query-by-label-text :url-preview-loading)))
(h/test "on-clear event"
(let [on-clear (h/mock-fn)]
(h/render [view/view {:on-clear on-clear}])
(h/fire-event :press (h/get-by-label-text :button-clear-preview))
(h/was-called on-clear)))
(h/describe "loading state"
(h/test "shows a loading container"
(h/render [view/view {:loading? true :loading-message "Hello"}])
(h/is-null (h/query-by-label-text :title))
(h/is-truthy (h/query-by-label-text :url-preview-loading)))
(h/test "renders if `loading-message` is not passed"
(h/render [view/view {:loading? true}])
(h/is-null (h/query-by-label-text :title))
(h/is-truthy (h/query-by-label-text :url-preview-loading)))))

View File

@ -0,0 +1,58 @@
(ns quo2.components.links.url-preview.style
(:require [quo2.foundations.colors :as colors]))
(def horizontal-padding 12)
(defn container
[]
{:height 56
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-90)
:padding-vertical 10
:padding-horizontal horizontal-padding
:border-radius 12
:align-self :stretch
:flex-direction :row})
(defn loading-container
[]
{:height 56
:border-width 1
:border-radius 12
:border-style :dashed
:align-items :center
:justify-content :center
:align-self :stretch
:padding horizontal-padding
:border-color (colors/theme-colors colors/neutral-30 colors/neutral-80)})
(defn loading-message
[]
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)})
(def logo
{:width 16
:height 16
:top 1
:border-radius 8})
(def content-container
{:margin-left 6
:flex 1})
(defn title
[]
{:color (colors/theme-colors colors/neutral-100 colors/white)})
(defn body
[]
{:text-transform :lowercase
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)})
(def clear-button
{:border-color colors/danger-50
:border-width 1})
(def clear-button-container
{:width 20
:height 20
:margin-left 6})

View File

@ -0,0 +1,63 @@
(ns quo2.components.links.url-preview.view
(:require
[quo2.components.icon :as icon]
[quo2.components.links.url-preview.style :as style]
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]))
(defn- logo-component
[{:keys [logo]}]
[rn/image
{:accessibility-label :logo
:source logo
:style style/logo}])
(defn- content
[{:keys [title body]}]
[rn/view {:style style/content-container}
[text/text
{:accessibility-label :title
:size :paragraph-2
:weight :semi-bold
:number-of-lines 1
:style (style/title)}
title]
[text/text
{:accessibility-label :body
:size :paragraph-2
:weight :medium
:number-of-lines 1
:style (style/body)}
body]])
(defn- clear-button
[{:keys [on-press]}]
[rn/touchable-opacity
{:on-press on-press
:style style/clear-button-container
:hit-slop {:top 3 :right 3 :bottom 3 :left 3}
:accessibility-label :button-clear-preview}
[icon/icon :i/clear
{:size 20
:container-style style/clear-button
:color (colors/theme-colors colors/neutral-50 colors/neutral-60)}]])
(defn view
[{:keys [title body logo on-clear loading? loading-message container-style]}]
(if loading?
[rn/view
{:accessibility-label :url-preview-loading
:style (merge (style/loading-container) container-style)}
[rn/text
{:size :paragraph-2
:weight :medium
:number-of-lines 1
:style (style/loading-message)}
loading-message]]
[rn/view
{:accessibility-label :url-preview
:style (merge (style/container) container-style)}
[logo-component {:logo logo}]
[content {:title title :body body}]
[clear-button {:on-press on-clear}]]))

View File

@ -33,6 +33,7 @@
quo2.components.inputs.input.view quo2.components.inputs.input.view
quo2.components.inputs.title-input.view quo2.components.inputs.title-input.view
quo2.components.inputs.profile-input.view quo2.components.inputs.profile-input.view
quo2.components.links.url-preview.view
quo2.components.list-items.channel quo2.components.list-items.channel
quo2.components.list-items.menu-item quo2.components.list-items.menu-item
quo2.components.list-items.preview-list quo2.components.list-items.preview-list
@ -182,3 +183,6 @@
(def permission-tag quo2.components.tags.permission-tag/tag) (def permission-tag quo2.components.tags.permission-tag/tag)
(def status-tag quo2.components.tags.status-tags/status-tag) (def status-tag quo2.components.tags.status-tags/status-tag)
(def token-tag quo2.components.tags.token-tag/tag) (def token-tag quo2.components.tags.token-tag/tag)
;;;; LINKS
(def url-preview quo2.components.links.url-preview.view/view)

View File

@ -1,5 +1,6 @@
(ns quo2.core-spec (ns quo2.core-spec
(:require [quo2.components.avatars.user-avatar.component-spec] (:require
[quo2.components.avatars.user-avatar.component-spec]
[quo2.components.banners.banner.component-spec] [quo2.components.banners.banner.component-spec]
[quo2.components.buttons.--tests--.buttons-component-spec] [quo2.components.buttons.--tests--.buttons-component-spec]
[quo2.components.colors.color-picker.component-spec] [quo2.components.colors.color-picker.component-spec]
@ -12,6 +13,7 @@
[quo2.components.inputs.input.component-spec] [quo2.components.inputs.input.component-spec]
[quo2.components.inputs.profile-input.component-spec] [quo2.components.inputs.profile-input.component-spec]
[quo2.components.inputs.title-input.component-spec] [quo2.components.inputs.title-input.component-spec]
[quo2.components.links.url-preview.component-spec]
[quo2.components.markdown.--tests--.text-component-spec] [quo2.components.markdown.--tests--.text-component-spec]
[quo2.components.onboarding.small-option-card.component-spec] [quo2.components.onboarding.small-option-card.component-spec]
[quo2.components.password.tips.component-spec] [quo2.components.password.tips.component-spec]

View File

@ -0,0 +1,56 @@
(ns status-im2.contexts.quo-preview.links.url-preview
(:require
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:label "Title"
:key :title
:type :text}
{:label "Body"
:key :body
:type :text}
{:label "Loading?"
:key :loading?
:type :boolean}
{:label "Loading message"
:key :loading-message
:type :text}])
(defn cool-preview
[]
(let [state (reagent/atom
{:title "Status - Private, Secure Communication"
:body "Status.im"
:loading? false
:loading-message "Generating preview"})]
(fn []
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:style {:padding-bottom 150}}
[preview/customizer state descriptor]
[rn/view
{:style {:align-items :center
:padding-horizontal 16
:margin-top 50}}
[quo/url-preview
{:title (:title @state)
:body (:body @state)
:logo (resources/get-mock-image :status-logo)
:loading? (:loading? @state)
:loading-message (:loading-message @state)
:on-clear #(js/alert "Clear button pressed")}]]]])))
(defn preview
[]
[rn/view
{:style {:background-color (colors/theme-colors colors/white colors/neutral-95)
:flex 1}}
[rn/flat-list
{:flex 1
:keyboard-should-persist-taps :always
:header [cool-preview]
:key-fn str}]])

View File

@ -39,6 +39,7 @@
[status-im2.contexts.quo-preview.info.information-box :as information-box] [status-im2.contexts.quo-preview.info.information-box :as information-box]
[status-im2.contexts.quo-preview.inputs.profile-input :as profile-input] [status-im2.contexts.quo-preview.inputs.profile-input :as profile-input]
[status-im2.contexts.quo-preview.inputs.title-input :as title-input] [status-im2.contexts.quo-preview.inputs.title-input :as title-input]
[status-im2.contexts.quo-preview.links.url-preview :as url-preview]
[status-im2.contexts.quo-preview.list-items.channel :as channel] [status-im2.contexts.quo-preview.list-items.channel :as channel]
[status-im2.contexts.quo-preview.list-items.preview-lists :as preview-lists] [status-im2.contexts.quo-preview.list-items.preview-lists :as preview-lists]
[status-im2.contexts.quo-preview.markdown.text :as text] [status-im2.contexts.quo-preview.markdown.text :as text]
@ -177,6 +178,9 @@
{:name :title-input {:name :title-input
:insets {:top false} :insets {:top false}
:component title-input/preview-title-input}] :component title-input/preview-title-input}]
:links [{:name :url-preview
:options {:insets {:top? true}}
:component url-preview/preview}]
:list-items [{:name :channel :list-items [{:name :channel
:insets {:top false} :insets {:top false}
:component channel/preview-channel} :component channel/preview-channel}

View File

@ -186,5 +186,5 @@
(.toBeNull (js/expect element))) (.toBeNull (js/expect element)))
(defn was-called (defn was-called
[element] [mock]
(.toHaveBeenCalled (js/expect element))) (.toHaveBeenCalled (js/expect mock)))