feat: category reorder component (#16719)

* feat: category reorder component

---------

Co-authored-by: Milad <mmilad.sanati@gmail.com>
This commit is contained in:
Omar Basem 2023-07-26 11:11:17 +04:00 committed by GitHub
parent 1721b40b3f
commit e49a3ab5cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 273 additions and 125 deletions

View File

@ -44,7 +44,7 @@
"react-native-camera-kit": "^13.0.0", "react-native-camera-kit": "^13.0.0",
"react-native-config": "^1.5.0", "react-native-config": "^1.5.0",
"react-native-dialogs": "^1.0.4", "react-native-dialogs": "^1.0.4",
"react-native-draggable-flatlist": "^3.0.3", "react-native-draggable-flatlist": "^4.0.1",
"react-native-fast-image": "^8.5.11", "react-native-fast-image": "^8.5.11",
"react-native-fetch-polyfill": "^1.1.2", "react-native-fetch-polyfill": "^1.1.2",
"react-native-fs": "^2.14.1", "react-native-fs": "^2.14.1",

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 KiB

View File

@ -1,20 +1,53 @@
(ns quo2.components.settings.category.component-spec (ns quo2.components.settings.category.component-spec
(:require [test-helpers.component :as h] (:require
[quo2.components.settings.category.view :as category])) [quo2.components.settings.category.view :as category]
[test-helpers.component :as h]))
(h/describe "category tests" (h/describe "Settings Category tests"
(h/test "category label renders" (h/test "category label renders"
(h/render [category/category (h/render [category/category
{:label "label" {:list-type :settings
:data [{:title "Item 1" :label "Label"
:left-icon :i/browser :data [{:title "Item 1"
:chevron? true}]}]) :left-icon :i/browser
(h/is-truthy (h/get-by-text "label"))) :chevron? true}]}])
(h/is-truthy (h/get-by-text "Label")))
(h/test "category item renders" (h/test "category item renders"
(h/render [category/category (h/render [category/category
{:label "label" {:list-type :settings
:data [{:title "Item 1" :label "Label"
:left-icon :i/browser :data [{:title "Item 1"
:chevron? true}]}]) :left-icon :i/browser
:chevron? true}]}])
(h/is-truthy (h/get-by-text "Item 1")))) (h/is-truthy (h/get-by-text "Item 1"))))
(h/describe "Reorder Category tests"
(h/test "category label renders"
(h/render [category/category
{:list-type :reorder
:label "Label"
:data [{:title "Item 1"
:right-icon :i/globe
:chevron? true}]}])
(h/is-truthy (h/get-by-text "Label")))
(h/test "category item renders"
(h/render [category/category
{:list-type :reorder
:label "Label"
:data [{:title "Item 1"
:right-icon :i/globe
:chevron? true}]}])
(h/is-truthy (h/get-by-text "Item 1")))
(h/test "category item subtitle renders"
(h/render [category/category
{:list-type :reorder
:label "Label"
:data [{:title "Item 1"
:subtitle "subtitle"
:right-icon :i/globe
:chevron? true}]}])
(h/is-truthy (h/get-by-text "subtitle"))))

View File

@ -0,0 +1,41 @@
(ns quo2.components.settings.category.reorder.view
(:require
[quo2.components.markdown.text :as text]
[quo2.components.settings.reorder-item.types :as types]
[quo2.components.settings.reorder-item.view :as reorder-item]
[quo2.foundations.colors :as colors]
[react-native.blur :as blur]
[react-native.core :as rn]
[quo2.components.settings.category.style :as style]
[quo2.theme :as quo.theme]
[react-native.draggable-flatlist :as draggable-flatlist]
[reagent.core :as reagent]))
(defn on-drag-end-fn
[data atom-data]
(reset! atom-data data)
(reagent/flush))
(defn- reorder-category-internal
[{:keys [label data blur? theme]}]
(reagent/with-let [atom-data (reagent/atom data)]
[rn/view {:style style/container}
(when blur?
[rn/view (style/blur-container) [blur/view (style/blur-view)]])
[text/text
{:weight :medium
:size :paragraph-2
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
label]
[draggable-flatlist/draggable-flatlist
{:data @atom-data
:key-fn (fn [item index] (str (:title item) index))
:style style/reorder-items
:render-fn (fn [item _ _ _ _ drag] [reorder-item/reorder-item item types/item
{:blur? blur? :drag drag}])
:on-drag-end-fn (fn [_ _ data]
(on-drag-end-fn data atom-data))
:separator [rn/view
{:style (style/reorder-separator blur? theme)}]}]]))
(def reorder-category (quo.theme/with-theme reorder-category-internal))

View File

@ -0,0 +1,27 @@
(ns quo2.components.settings.category.settings.view
(:require
[quo2.components.markdown.text :as text]
[quo2.components.settings.settings-list.view :as settings-list]
[quo2.foundations.colors :as colors]
[react-native.blur :as blur]
[react-native.core :as rn]
[quo2.components.settings.category.style :as style]
[quo2.theme :as quo.theme]))
(defn- category-internal
[{:keys [label data blur? theme]}]
[rn/view {:style style/container}
(when blur?
[rn/view (style/blur-container) [blur/view (style/blur-view)]])
[text/text
{:weight :medium
:size :paragraph-2
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
label]
[rn/flat-list
{:data data
:style (style/settings-items theme blur?)
:render-fn (fn [item] [settings-list/settings-list item])
:separator [rn/view {:style (style/settings-separator theme blur?)}]}]])
(def settings-category (quo.theme/with-theme category-internal))

View File

@ -8,7 +8,7 @@
:padding-top 12 :padding-top 12
:padding-bottom 8}) :padding-bottom 8})
(defn items (defn settings-items
[theme blur?] [theme blur?]
{:margin-top 12 {:margin-top 12
:border-radius 16 :border-radius 16
@ -20,13 +20,23 @@
colors/white-opa-5 colors/white-opa-5
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))}) (colors/theme-colors colors/neutral-10 colors/neutral-80 theme))})
(defn separator (def reorder-items
{:margin-top 12})
(defn settings-separator
[theme blur?] [theme blur?]
{:height 1 {:height 1
:background-color (if blur? :background-color (if blur?
colors/white-opa-5 colors/white-opa-5
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))}) (colors/theme-colors colors/neutral-10 colors/neutral-80 theme))})
(defn reorder-separator
[blur? theme]
{:height 4
:background-color (if blur?
:transparent
(colors/theme-colors colors/neutral-5 colors/neutral-95 theme))})
(defn blur-container (defn blur-container
[] []
{:position :absolute {:position :absolute

View File

@ -1,27 +1,9 @@
(ns quo2.components.settings.category.view (ns quo2.components.settings.category.view
(:require (:require [quo2.components.settings.category.settings.view :as settings]
[quo2.components.markdown.text :as text] [quo2.components.settings.category.reorder.view :as reorder]))
[quo2.components.settings.settings-list.view :as settings-list]
[quo2.foundations.colors :as colors]
[react-native.blur :as blur]
[react-native.core :as rn]
[quo2.components.settings.category.style :as style]
[quo2.theme :as quo.theme]))
(defn- category-internal (defn category
[{:keys [label data blur? theme]}] [{:keys [list-type] :as props}]
[rn/view {:style style/container} (if (= list-type :settings)
(when blur? [settings/settings-category props]
[rn/view (style/blur-container) [blur/view (style/blur-view)]]) [reorder/reorder-category props]))
[text/text
{:weight :medium
:size :paragraph-2
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
label]
[rn/flat-list
{:data data
:style (style/items theme blur?)
:render-fn (fn [item] [settings-list/settings-list item])
:separator [rn/view {:style (style/separator theme blur?)}]}]])
(def category (quo.theme/with-theme category-internal))

View File

@ -1,11 +1,14 @@
(ns quo2.components.settings.reorder-item.items.item (ns quo2.components.settings.reorder-item.items.item
(:require [react-native.core :as rn] (:require
[quo2.components.settings.reorder-item.style :as style] [quo2.theme :as quo.theme]
[quo2.components.markdown.text :as text] [react-native.core :as rn]
[quo2.components.icon :as icon] [quo2.components.settings.reorder-item.style :as style]
[quo2.foundations.colors :as colors])) [quo2.components.markdown.text :as text]
[quo2.components.icon :as icon]
[quo2.foundations.colors :as colors]
[react-native.fast-image :as fast-image]))
(defn view (defn- view-internal
[{:keys [{:keys
[title [title
subtitle subtitle
@ -13,10 +16,14 @@
image-size image-size
right-text right-text
right-icon right-icon
on-press]}] on-press
theme]}
blur?
drag]
[rn/touchable-opacity [rn/touchable-opacity
{:on-press on-press {:on-press on-press
:style (merge (style/item-container) (when subtitle style/item-container-extended))} :on-long-press drag
:style (merge (style/item-container blur?) (when subtitle style/item-container-extended))}
[icon/icon :main-icons/drag [icon/icon :main-icons/drag
{:color (colors/theme-colors {:color (colors/theme-colors
colors/neutral-50 colors/neutral-50
@ -25,23 +32,25 @@
{:style style/body-container} {:style style/body-container}
[rn/view [rn/view
{:style style/image-container} {:style style/image-container}
[rn/image [fast-image/fast-image
{:source image {:source image
:style (style/image image-size)}]] :style (style/image image-size)}]]
[rn/view [rn/view
{:style style/text-container} {:style style/text-container}
[rn/view [rn/view
[text/text [text/text
{:style style/item-text {:weight :medium}
:weight :medium}
title] title]
(when subtitle (when subtitle
[text/text [text/text
{:style style/item-subtitle {:style style/item-subtitle
:weight :regular} :size :paragraph-2}
subtitle])] subtitle])]
(when right-text (when right-text
[text/text {:style style/right-text} right-text]) [text/text {:style style/right-text} right-text])
(when right-icon (when right-icon
[rn/view {:style style/right-icon-container} [icon/icon right-icon (style/right-icon)]])]] [rn/view {:style style/right-icon-container} [icon/icon right-icon (style/right-icon)]])]]
[icon/icon :tiny-icons/chevron-right (style/chevron)]]) [icon/icon :tiny-icons/chevron-right (style/chevron theme)]])
(def view (quo.theme/with-theme view-internal))

View File

@ -2,19 +2,21 @@
(:require [quo2.foundations.colors :as colors])) (:require [quo2.foundations.colors :as colors]))
(defn item-container (defn item-container
[] [blur?]
{:flex-direction :row {:flex-direction :row
:align-items :center :align-items :center
:padding-horizontal 10 :border-radius 16
:border-radius 14 :padding-horizontal 12
:margin-bottom 23 :padding-vertical 12
:height 45 :height 48
:background-color (colors/theme-colors :background-color (if blur?
colors/white colors/white-opa-5
colors/neutral-90)}) (colors/theme-colors
colors/white
colors/neutral-90))})
(def item-container-extended (def item-container-extended
{:height 52}) {:height 56})
(def body-container (def body-container
{:flex 1 {:flex 1
@ -31,20 +33,17 @@
{:width size {:width size
:height size}) :height size})
(def item-text
{:font-size 14})
(defn chevron (defn chevron
[] [theme]
{:color (colors/theme-colors {:color (colors/theme-colors
colors/neutral-50 colors/neutral-50
colors/neutral-40) colors/neutral-40
theme)
:height 14 :height 14
:width 14}) :width 14})
(def item-subtitle (def item-subtitle
{:color colors/neutral-50 {:color colors/neutral-50})
:font-size 13})
(def right-text (def right-text
{:font-size 15 {:font-size 15

View File

@ -7,9 +7,9 @@
[quo2.components.settings.reorder-item.types :as types])) [quo2.components.settings.reorder-item.types :as types]))
(defn reorder-item (defn reorder-item
[item type] [item type {:keys [blur? drag]}]
(case type (case type
types/item [item/view item] types/item [item/view item blur? drag]
types/placeholder [placeholder/view item] types/placeholder [placeholder/view item]
types/skeleton [skeleton/view] types/skeleton [skeleton/view]
types/tab [tab/view item] types/tab [tab/view item]

View File

@ -0,0 +1,11 @@
(ns react-native.draggable-flatlist
(:require
[react-native.flat-list :as rn-flat-list]
[reagent.core :as reagent]
["react-native-draggable-flatlist" :default DraggableFlatList]))
(def rn-draggable-flatlist (reagent/adapt-react-class DraggableFlatList))
(defn draggable-flatlist
[props]
[rn-draggable-flatlist (rn-flat-list/base-list-props props)])

View File

@ -57,6 +57,7 @@
:community-banner (js/require "../resources/images/mock2/community-banner.png") :community-banner (js/require "../resources/images/mock2/community-banner.png")
:community-logo (js/require "../resources/images/mock2/community-logo.png") :community-logo (js/require "../resources/images/mock2/community-logo.png")
:community-cover (js/require "../resources/images/mock2/community-cover.png") :community-cover (js/require "../resources/images/mock2/community-cover.png")
:dark-blur-bg (js/require "../resources/images/mock2/dark_blur_bg.png")
:decentraland (js/require "../resources/images/mock2/decentraland.png") :decentraland (js/require "../resources/images/mock2/decentraland.png")
:gif (js/require "../resources/images/mock2/gif.png") :gif (js/require "../resources/images/mock2/gif.png")
:monkey (js/require "../resources/images/mock2/monkey.png") :monkey (js/require "../resources/images/mock2/monkey.png")

View File

@ -80,6 +80,7 @@
[status-im2.contexts.quo-preview.settings.settings-list :as settings-list] [status-im2.contexts.quo-preview.settings.settings-list :as settings-list]
[status-im2.contexts.quo-preview.settings.privacy-option :as privacy-option] [status-im2.contexts.quo-preview.settings.privacy-option :as privacy-option]
[status-im2.contexts.quo-preview.settings.reorder-item :as reorder-item] [status-im2.contexts.quo-preview.settings.reorder-item :as reorder-item]
[status-im2.contexts.quo-preview.settings.category :as category]
[status-im2.contexts.quo-preview.share.qr-code :as qr-code] [status-im2.contexts.quo-preview.share.qr-code :as qr-code]
[status-im2.contexts.quo-preview.share.share-qr-code :as share-qr-code] [status-im2.contexts.quo-preview.share.share-qr-code :as share-qr-code]
[status-im2.contexts.quo-preview.switcher.switcher-cards :as switcher-cards] [status-im2.contexts.quo-preview.switcher.switcher-cards :as switcher-cards]
@ -97,7 +98,6 @@
[status-im2.contexts.quo-preview.wallet.network-amount :as network-amount] [status-im2.contexts.quo-preview.wallet.network-amount :as network-amount]
[status-im2.contexts.quo-preview.wallet.network-breakdown :as network-breakdown] [status-im2.contexts.quo-preview.wallet.network-breakdown :as network-breakdown]
[status-im2.contexts.quo-preview.wallet.token-overview :as token-overview] [status-im2.contexts.quo-preview.wallet.token-overview :as token-overview]
[status-im2.contexts.quo-preview.settings.category :as category]
[status-im2.contexts.quo-preview.keycard.keycard :as keycard] [status-im2.contexts.quo-preview.keycard.keycard :as keycard]
[status-im2.contexts.quo-preview.loaders.skeleton :as skeleton] [status-im2.contexts.quo-preview.loaders.skeleton :as skeleton]
[status-im2.contexts.quo-preview.community.channel-actions :as channel-actions])) [status-im2.contexts.quo-preview.community.channel-actions :as channel-actions]))

View File

@ -6,60 +6,91 @@
[react-native.core :as rn] [react-native.core :as rn]
[react-native.fast-image :as fast-image] [react-native.fast-image :as fast-image]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview])) [status-im2.contexts.quo-preview.preview :as preview]))
(def item (defn create-item-array
{:title "Item 1" [n {:keys [right-icon? image? subtitle?]}]
:left-icon :i/browser (vec (for [i (range n)]
:chevron? true}) {:title (str "Item " i)
:subtitle (when subtitle? "subtitle")
:chevron? true
:right-icon (when right-icon? :i/globe)
:left-icon :i/browser
:image-size (if image? 32 0)
:image (when image? (resources/get-mock-image :diamond))})))
(def descriptor (def reorder-descriptor
[{:label "Category label:" [{:label "Right icon:"
:key :label :key :right-icon?
:type :text} :type :boolean}
{:label "Category size:" {:label "Image:"
:key :size :key :image?
:type :text} :type :boolean}
{:label "Subtitle:"
:key :subtitle?
:type :boolean}
{:label "Blur:" {:label "Blur:"
:key :blur? :key :blur?
:type :boolean}]) :type :boolean}
{:label "List type:"
:key :list-type
:type :select
:options [{:key :settings :value :settings} {:key :reorder :value :reorder}]}])
(def image-uri (def settings-descriptor
"https://4kwallpapers.com/images/wallpapers/giau-pass-mountain-pass-italy-dolomites-landscape-mountain-750x1334-4282.jpg") [{:label "Blur:"
:key :blur?
(def label "Label") :type :boolean}
{:label "List type:"
:key :list-type
:type :select
:options [{:key :settings :value :settings} {:key :reorder :value :reorder}]}])
(defn preview (defn preview
[] []
(let [state (reagent/atom {:label "Label" (let [state (reagent/atom {:label "Label"
:size "5" :size "5"
:blur? false}) :blur? false
:right-icon? true
:image? true
:subtitle? true
:list-type :settings})
{:keys [width height]} (rn/get-window)] {:keys [width height]} (rn/get-window)]
[:f> (fn []
(fn [] (let [data (reagent/atom (create-item-array (max (js/parseInt (:size @state)) 1) @state))]
(let [data (repeat (js/parseInt (:size @state)) item)] [:f>
(rn/use-effect (fn [] (fn []
(if (:blur? @state) (rn/use-effect (fn []
(theme/set-theme :dark) (if (:blur? @state)
(theme/set-theme :light))) (theme/set-theme :dark)
[(:blur? @state)]) (theme/set-theme :light))
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} (reset! data (create-item-array (max (js/parseInt (:size @state)) 1)
[rn/view @state)))
{:style {:flex 1 [(:blur? @state) (:right-icon? @state) (:image? @state) (:subtitle? @state)])
:padding-bottom 150 [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
:margin-bottom 50 [rn/view
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}} {:style {:flex 1
[rn/view :padding-bottom 150
{:style {:min-height 180 :margin-bottom 50
:z-index 1}} [preview/customizer state descriptor]] :background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}}
(when (:blur? @state) [rn/view
[fast-image/fast-image {:style {:min-height 200
{:source {:uri image-uri} :z-index 1}}
:style {:width width [preview/customizer state
:height height (if (= (:list-type @state) :settings) settings-descriptor reorder-descriptor)]]
:position :absolute}}]) (when (:blur? @state)
[rn/view [fast-image/fast-image
{:style {:background-color (if (:blur? @state) {:source (resources/get-mock-image :dark-blur-bg)
colors/neutral-80-opa-80 :style {:width width
(colors/theme-colors colors/neutral-5 colors/neutral-95))}} :height height
[quo/category {:label (:label @state) :data data :blur? (:blur? @state)}]]]]))])) :position :absolute}}])
[rn/view
{:style {:background-color (if (:blur? @state)
colors/neutral-80-opa-80
(colors/theme-colors colors/neutral-5 colors/neutral-95))}}
[quo/category
{:list-type (:list-type @state)
:label (:label @state)
:data @data
:blur? (:blur? @state)}]]]])]))))

View File

@ -76,6 +76,8 @@ jest.mock('react-native-blob-util', () => ({
}, },
})); }));
jest.mock('react-native-reanimated', () => require('react-native-reanimated/mock'));
NativeModules.ReactLocalization = { NativeModules.ReactLocalization = {
language: 'en', language: 'en',
locale: 'en', locale: 'en',

View File

@ -8813,10 +8813,12 @@ react-native-dialogs@^1.0.4:
resolved "https://registry.yarnpkg.com/react-native-dialogs/-/react-native-dialogs-1.1.0.tgz#8f7ee7f9d96574fc878fb7c1be101611fb4af517" resolved "https://registry.yarnpkg.com/react-native-dialogs/-/react-native-dialogs-1.1.0.tgz#8f7ee7f9d96574fc878fb7c1be101611fb4af517"
integrity sha512-clnxO0nMyML/6+G5dja3Yt34gPxegLY2OHTwb8BwYTEvQ2UhRKR49Uq91XqU0q6g7Ur9DiYxC0tqV3rcZWUrjQ== integrity sha512-clnxO0nMyML/6+G5dja3Yt34gPxegLY2OHTwb8BwYTEvQ2UhRKR49Uq91XqU0q6g7Ur9DiYxC0tqV3rcZWUrjQ==
react-native-draggable-flatlist@^3.0.3: react-native-draggable-flatlist@^4.0.1:
version "3.0.3" version "4.0.1"
resolved "https://registry.yarnpkg.com/react-native-draggable-flatlist/-/react-native-draggable-flatlist-3.0.3.tgz#e85503585253be01ad251f78d5b341ac22f9d952" resolved "https://registry.yarnpkg.com/react-native-draggable-flatlist/-/react-native-draggable-flatlist-4.0.1.tgz#2f027d387ba4b8f3eb0907340e32cb85e6460df2"
integrity sha512-bDro6aqQMvvTm/CuHre9dAjSBKosAfZRLDx3nmrjOz799kxcn0bq+uCB6yF6m+g1Xd/gVPl7E3Ss4uX+oPUlHg== integrity sha512-ZO1QUTNx64KZfXGXeXcBfql67l38X7kBcJ3rxUVZzPHt5r035GnGzIC0F8rqSXp6zgnwgUYMfB6zQc5PKmPL9Q==
dependencies:
"@babel/preset-typescript" "^7.17.12"
react-native-fast-image@^8.5.11: react-native-fast-image@^8.5.11:
version "8.5.11" version "8.5.11"