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-config": "^1.5.0",
"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-fetch-polyfill": "^1.1.2",
"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
(:require [test-helpers.component :as h]
[quo2.components.settings.category.view :as category]))
(:require
[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/render [category/category
{:label "label"
:data [{:title "Item 1"
:left-icon :i/browser
:chevron? true}]}])
(h/is-truthy (h/get-by-text "label")))
{:list-type :settings
:label "Label"
:data [{:title "Item 1"
:left-icon :i/browser
:chevron? true}]}])
(h/is-truthy (h/get-by-text "Label")))
(h/test "category item renders"
(h/render [category/category
{:label "label"
:data [{:title "Item 1"
:left-icon :i/browser
:chevron? true}]}])
{:list-type :settings
:label "Label"
:data [{:title "Item 1"
:left-icon :i/browser
:chevron? true}]}])
(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-bottom 8})
(defn items
(defn settings-items
[theme blur?]
{:margin-top 12
:border-radius 16
@ -20,13 +20,23 @@
colors/white-opa-5
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))})
(defn separator
(def reorder-items
{:margin-top 12})
(defn settings-separator
[theme blur?]
{:height 1
:background-color (if blur?
colors/white-opa-5
(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
[]
{:position :absolute

View File

@ -1,27 +1,9 @@
(ns quo2.components.settings.category.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]))
(:require [quo2.components.settings.category.settings.view :as settings]
[quo2.components.settings.category.reorder.view :as reorder]))
(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/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))
(defn category
[{:keys [list-type] :as props}]
(if (= list-type :settings)
[settings/settings-category props]
[reorder/reorder-category props]))

View File

@ -1,11 +1,14 @@
(ns quo2.components.settings.reorder-item.items.item
(:require [react-native.core :as rn]
[quo2.components.settings.reorder-item.style :as style]
[quo2.components.markdown.text :as text]
[quo2.components.icon :as icon]
[quo2.foundations.colors :as colors]))
(:require
[quo2.theme :as quo.theme]
[react-native.core :as rn]
[quo2.components.settings.reorder-item.style :as style]
[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
[title
subtitle
@ -13,10 +16,14 @@
image-size
right-text
right-icon
on-press]}]
on-press
theme]}
blur?
drag]
[rn/touchable-opacity
{:on-press on-press
:style (merge (style/item-container) (when subtitle style/item-container-extended))}
{:on-press on-press
:on-long-press drag
:style (merge (style/item-container blur?) (when subtitle style/item-container-extended))}
[icon/icon :main-icons/drag
{:color (colors/theme-colors
colors/neutral-50
@ -25,23 +32,25 @@
{:style style/body-container}
[rn/view
{:style style/image-container}
[rn/image
[fast-image/fast-image
{:source image
:style (style/image image-size)}]]
[rn/view
{:style style/text-container}
[rn/view
[text/text
{:style style/item-text
:weight :medium}
{:weight :medium}
title]
(when subtitle
[text/text
{:style style/item-subtitle
:weight :regular}
{:style style/item-subtitle
:size :paragraph-2}
subtitle])]
(when right-text
[text/text {:style style/right-text} right-text])
(when 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]))
(defn item-container
[]
[blur?]
{:flex-direction :row
:align-items :center
:padding-horizontal 10
:border-radius 14
:margin-bottom 23
:height 45
:background-color (colors/theme-colors
colors/white
colors/neutral-90)})
:border-radius 16
:padding-horizontal 12
:padding-vertical 12
:height 48
:background-color (if blur?
colors/white-opa-5
(colors/theme-colors
colors/white
colors/neutral-90))})
(def item-container-extended
{:height 52})
{:height 56})
(def body-container
{:flex 1
@ -31,20 +33,17 @@
{:width size
:height size})
(def item-text
{:font-size 14})
(defn chevron
[]
[theme]
{:color (colors/theme-colors
colors/neutral-50
colors/neutral-40)
colors/neutral-40
theme)
:height 14
:width 14})
(def item-subtitle
{:color colors/neutral-50
:font-size 13})
{:color colors/neutral-50})
(def right-text
{:font-size 15

View File

@ -7,9 +7,9 @@
[quo2.components.settings.reorder-item.types :as types]))
(defn reorder-item
[item type]
[item type {:keys [blur? drag]}]
(case type
types/item [item/view item]
types/item [item/view item blur? drag]
types/placeholder [placeholder/view item]
types/skeleton [skeleton/view]
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-logo (js/require "../resources/images/mock2/community-logo.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")
:gif (js/require "../resources/images/mock2/gif.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.privacy-option :as privacy-option]
[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.share-qr-code :as share-qr-code]
[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-breakdown :as network-breakdown]
[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.loaders.skeleton :as skeleton]
[status-im2.contexts.quo-preview.community.channel-actions :as channel-actions]))

View File

@ -6,60 +6,91 @@
[react-native.core :as rn]
[react-native.fast-image :as fast-image]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
(def item
{:title "Item 1"
:left-icon :i/browser
:chevron? true})
(defn create-item-array
[n {:keys [right-icon? image? subtitle?]}]
(vec (for [i (range n)]
{: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
[{:label "Category label:"
:key :label
:type :text}
{:label "Category size:"
:key :size
:type :text}
(def reorder-descriptor
[{:label "Right icon:"
:key :right-icon?
:type :boolean}
{:label "Image:"
:key :image?
:type :boolean}
{:label "Subtitle:"
:key :subtitle?
:type :boolean}
{:label "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
"https://4kwallpapers.com/images/wallpapers/giau-pass-mountain-pass-italy-dolomites-landscape-mountain-750x1334-4282.jpg")
(def label "Label")
(def settings-descriptor
[{:label "Blur:"
:key :blur?
:type :boolean}
{:label "List type:"
:key :list-type
:type :select
:options [{:key :settings :value :settings} {:key :reorder :value :reorder}]}])
(defn preview
[]
(let [state (reagent/atom {:label "Label"
:size "5"
:blur? false})
(let [state (reagent/atom {:label "Label"
:size "5"
:blur? false
:right-icon? true
:image? true
:subtitle? true
:list-type :settings})
{:keys [width height]} (rn/get-window)]
[:f>
(fn []
(let [data (repeat (js/parseInt (:size @state)) item)]
(rn/use-effect (fn []
(if (:blur? @state)
(theme/set-theme :dark)
(theme/set-theme :light)))
[(:blur? @state)])
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view
{:style {:flex 1
:padding-bottom 150
:margin-bottom 50
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}}
[rn/view
{:style {:min-height 180
:z-index 1}} [preview/customizer state descriptor]]
(when (:blur? @state)
[fast-image/fast-image
{:source {:uri image-uri}
:style {:width width
:height height
: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 {:label (:label @state) :data data :blur? (:blur? @state)}]]]]))]))
(fn []
(let [data (reagent/atom (create-item-array (max (js/parseInt (:size @state)) 1) @state))]
[:f>
(fn []
(rn/use-effect (fn []
(if (:blur? @state)
(theme/set-theme :dark)
(theme/set-theme :light))
(reset! data (create-item-array (max (js/parseInt (:size @state)) 1)
@state)))
[(:blur? @state) (:right-icon? @state) (:image? @state) (:subtitle? @state)])
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view
{:style {:flex 1
:padding-bottom 150
:margin-bottom 50
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}}
[rn/view
{:style {:min-height 200
:z-index 1}}
[preview/customizer state
(if (= (:list-type @state) :settings) settings-descriptor reorder-descriptor)]]
(when (:blur? @state)
[fast-image/fast-image
{:source (resources/get-mock-image :dark-blur-bg)
:style {:width width
:height height
: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 = {
language: '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"
integrity sha512-clnxO0nMyML/6+G5dja3Yt34gPxegLY2OHTwb8BwYTEvQ2UhRKR49Uq91XqU0q6g7Ur9DiYxC0tqV3rcZWUrjQ==
react-native-draggable-flatlist@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/react-native-draggable-flatlist/-/react-native-draggable-flatlist-3.0.3.tgz#e85503585253be01ad251f78d5b341ac22f9d952"
integrity sha512-bDro6aqQMvvTm/CuHre9dAjSBKosAfZRLDx3nmrjOz799kxcn0bq+uCB6yF6m+g1Xd/gVPl7E3Ss4uX+oPUlHg==
react-native-draggable-flatlist@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/react-native-draggable-flatlist/-/react-native-draggable-flatlist-4.0.1.tgz#2f027d387ba4b8f3eb0907340e32cb85e6460df2"
integrity sha512-ZO1QUTNx64KZfXGXeXcBfql67l38X7kBcJ3rxUVZzPHt5r035GnGzIC0F8rqSXp6zgnwgUYMfB6zQc5PKmPL9Q==
dependencies:
"@babel/preset-typescript" "^7.17.12"
react-native-fast-image@^8.5.11:
version "8.5.11"