feat: category reorder component (#16719)
* feat: category reorder component --------- Co-authored-by: Milad <mmilad.sanati@gmail.com>
This commit is contained in:
parent
1721b40b3f
commit
e49a3ab5cd
|
@ -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 |
|
@ -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"
|
||||
{:list-type :settings
|
||||
:label "Label"
|
||||
:data [{:title "Item 1"
|
||||
:left-icon :i/browser
|
||||
:chevron? true}]}])
|
||||
(h/is-truthy (h/get-by-text "label")))
|
||||
(h/is-truthy (h/get-by-text "Label")))
|
||||
|
||||
(h/test "category item renders"
|
||||
(h/render [category/category
|
||||
{:label "label"
|
||||
{: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"))))
|
||||
|
|
|
@ -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))
|
|
@ -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))
|
|
@ -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
|
||||
|
|
|
@ -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]))
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
(ns quo2.components.settings.reorder-item.items.item
|
||||
(:require [react-native.core :as rn]
|
||||
(: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]))
|
||||
[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-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}
|
||||
: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))
|
||||
|
|
|
@ -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
|
||||
: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)})
|
||||
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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)])
|
|
@ -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")
|
||||
|
|
|
@ -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]))
|
||||
|
|
|
@ -6,43 +6,68 @@
|
|||
[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"
|
||||
(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
|
||||
:chevron? true})
|
||||
: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})
|
||||
:blur? false
|
||||
:right-icon? true
|
||||
:image? true
|
||||
:subtitle? true
|
||||
:list-type :settings})
|
||||
{:keys [width height]} (rn/get-window)]
|
||||
(fn []
|
||||
(let [data (reagent/atom (create-item-array (max (js/parseInt (:size @state)) 1) @state))]
|
||||
[: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)])
|
||||
(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
|
||||
|
@ -50,11 +75,13 @@
|
|||
: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]]
|
||||
{: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 {:uri image-uri}
|
||||
{:source (resources/get-mock-image :dark-blur-bg)
|
||||
:style {:width width
|
||||
:height height
|
||||
:position :absolute}}])
|
||||
|
@ -62,4 +89,8 @@
|
|||
{: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)}]]]]))]))
|
||||
[quo/category
|
||||
{:list-type (:list-type @state)
|
||||
:label (:label @state)
|
||||
:data @data
|
||||
:blur? (:blur? @state)}]]]])]))))
|
||||
|
|
|
@ -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',
|
||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue