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:
parent
ccb20d7994
commit
bfc7a2d88b
|
@ -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)))))
|
|
@ -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})
|
|
@ -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}]]))
|
|
@ -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)
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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}]])
|
|
@ -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}
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
Loading…
Reference in New Issue