Reorder community chats and categories using drag and drop (#12854)
This commit is contained in:
parent
5402c217df
commit
94fde74b88
|
@ -163,4 +163,8 @@ used for some abi encoding primitives
|
|||
|
||||
## "rn-emoji-keyboard": "https://github.com/status-im/rn-emoji-keyboard"
|
||||
|
||||
Used for taking emoji input, for custom emoji thumbnails for community channels
|
||||
Used for taking emoji input, for custom emoji thumbnails for community channels
|
||||
|
||||
## "react-native-draggable-flatlist": "https://github.com/computerjazz/react-native-draggable-flatlist"
|
||||
|
||||
A drag-and-drop-enabled FlatList component for React Native
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
"react-native-dark-mode": "^0.2.2",
|
||||
"react-native-device-info": "^7.4.0",
|
||||
"react-native-dialogs": "^1.0.4",
|
||||
"react-native-draggable-flatlist": "^3.0.3",
|
||||
"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: 196 B |
Binary file not shown.
After Width: | Height: | Size: 250 B |
|
@ -206,6 +206,9 @@
|
|||
(def rn-emoji-keyboard
|
||||
#js {:EmojiKeyboard #js {}})
|
||||
|
||||
(def react-native-draggable-flatlist
|
||||
#js {:default #js {}})
|
||||
|
||||
;; Update i18n_resources.cljs
|
||||
(defn mock [module]
|
||||
(case module
|
||||
|
@ -239,6 +242,7 @@
|
|||
"@react-native-community/push-notification-ios" push-notification-ios
|
||||
"react-native-camera-kit" react-native-camera-kit
|
||||
"rn-emoji-keyboard" rn-emoji-keyboard
|
||||
"react-native-draggable-flatlist" react-native-draggable-flatlist
|
||||
"./fleets.js" default-fleets
|
||||
"./chats.js" default-chats
|
||||
"../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json"))
|
||||
|
|
|
@ -55,13 +55,13 @@
|
|||
:small :base
|
||||
:large))
|
||||
|
||||
(defn container [{:keys [size]} & children]
|
||||
(defn container [{:keys [size container-style]} & children]
|
||||
(into [rn/view {:style (merge (:tiny spacing/padding-horizontal)
|
||||
{:min-height (size->container-size size)
|
||||
:padding-vertical 8
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between})}]
|
||||
:justify-content :space-between} container-style)}]
|
||||
children))
|
||||
|
||||
(defn icon-column
|
||||
|
@ -197,7 +197,7 @@
|
|||
left-side-alignment icon-color icon-bg-color
|
||||
title subtitle subtitle-secondary active on-press on-long-press chevron size text-size
|
||||
accessory-text accessibility-label title-accessibility-label accessory-style
|
||||
haptic-feedback haptic-type error animated animated-accessory? title-text-weight]
|
||||
haptic-feedback haptic-type error animated animated-accessory? title-text-weight container-style]
|
||||
:or {subtitle-max-lines 1
|
||||
theme :main
|
||||
haptic-feedback true
|
||||
|
@ -233,7 +233,7 @@
|
|||
{:on-long-press (fn []
|
||||
(optional-haptic)
|
||||
(on-long-press))}))
|
||||
[container {:size size}
|
||||
[container {:size size :container-style container-style}
|
||||
[left-side {:icon-color icon-color
|
||||
:text-color (if on-press
|
||||
text-color
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
["react-native" :as rn]
|
||||
["@react-native-community/hooks" :as hooks]
|
||||
["react-native-navigation" :refer (Navigation)]
|
||||
["rn-emoji-keyboard" :refer (EmojiKeyboard)]))
|
||||
["rn-emoji-keyboard" :refer (EmojiKeyboard)]
|
||||
["react-native-draggable-flatlist" :default DraggableFlatList]))
|
||||
|
||||
(def rn-draggable-flatlist (reagent/adapt-react-class DraggableFlatList))
|
||||
|
||||
(def emoji-keyboard (reagent/adapt-react-class EmojiKeyboard))
|
||||
|
||||
|
@ -107,7 +110,13 @@
|
|||
|
||||
(defn- wrap-render-fn [f render-data]
|
||||
(fn [data]
|
||||
(reagent/as-element [f (.-item ^js data) (.-index ^js data) (.-separators ^js data) render-data])))
|
||||
(reagent/as-element [f (.-item ^js data) (.-index ^js data)
|
||||
(.-separators ^js data) render-data
|
||||
(.-isActive ^js data) (.-drag ^js data)])))
|
||||
|
||||
(defn- wrap-on-drag-end-fn [f]
|
||||
(fn [data]
|
||||
(f (.-from ^js data) (.-to ^js data) (.-data ^js data))))
|
||||
|
||||
(defn- wrap-key-fn [f]
|
||||
(fn [data index]
|
||||
|
@ -115,19 +124,23 @@
|
|||
(f data index)))
|
||||
|
||||
(defn base-list-props
|
||||
[{:keys [key-fn render-fn empty-component header footer separator data render-data] :as props}]
|
||||
[{:keys [key-fn render-fn empty-component header footer separator data render-data on-drag-end-fn] :as props}]
|
||||
(merge {:data (to-array data)}
|
||||
(when key-fn {:keyExtractor (wrap-key-fn key-fn)})
|
||||
(when render-fn {:renderItem (wrap-render-fn render-fn render-data)})
|
||||
(when separator {:ItemSeparatorComponent (fn [] (reagent/as-element separator))})
|
||||
(when empty-component {:ListEmptyComponent (fn [] (reagent/as-element empty-component))})
|
||||
(when header {:ListHeaderComponent (reagent/as-element header)})
|
||||
(when footer {:ListFooterComponent (reagent/as-element footer)})
|
||||
(dissoc props :data :header :footer :empty-component :separator :render-fn :key-fn)))
|
||||
(when key-fn {:keyExtractor (wrap-key-fn key-fn)})
|
||||
(when render-fn {:renderItem (wrap-render-fn render-fn render-data)})
|
||||
(when separator {:ItemSeparatorComponent (fn [] (reagent/as-element separator))})
|
||||
(when empty-component {:ListEmptyComponent (fn [] (reagent/as-element empty-component))})
|
||||
(when header {:ListHeaderComponent (reagent/as-element header)})
|
||||
(when footer {:ListFooterComponent (reagent/as-element footer)})
|
||||
(when on-drag-end-fn {:onDragEnd (wrap-on-drag-end-fn on-drag-end-fn)})
|
||||
(dissoc props :data :header :footer :empty-component :separator :render-fn :key-fn :on-drag-end-fn)))
|
||||
|
||||
(defn flat-list [props]
|
||||
[rn-flat-list (base-list-props props)])
|
||||
|
||||
(defn draggable-flat-list [props]
|
||||
[rn-draggable-flatlist (base-list-props props)])
|
||||
|
||||
(defn animated-flat-list [props]
|
||||
[animated-flat-list-class (base-list-props props)])
|
||||
;; Hooks
|
||||
|
|
|
@ -288,7 +288,7 @@
|
|||
(fx/defn edit-channel
|
||||
{:events [::edit-channel-confirmation-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [name description color community-id emoji edit-channel-id category-id]}
|
||||
(let [{:keys [name description color community-id emoji edit-channel-id category-id position]}
|
||||
(get db :communities/create-channel)]
|
||||
{::json-rpc/call [{:method "wakuext_editCommunityChat"
|
||||
:params [community-id
|
||||
|
@ -298,6 +298,7 @@
|
|||
:color color
|
||||
:emoji emoji}
|
||||
:category_id category-id
|
||||
:position position
|
||||
:permissions {:access constants/community-channel-access-no-membership}}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::community-channel-edited %])
|
||||
|
@ -345,7 +346,7 @@
|
|||
|
||||
(fx/defn edit-channel-pressed
|
||||
{:events [::edit-channel-pressed]}
|
||||
[{:keys [db] :as cofx} community-id chat-name description color emoji chat-id category-id]
|
||||
[{:keys [db] :as cofx} community-id chat-name description color emoji chat-id category-id position]
|
||||
(let [{:keys [color emoji]} (if (string/blank? emoji)
|
||||
(rand-nth emoji-thumbnail-styles/emoji-picker-default-thumbnails)
|
||||
{:color color :emoji emoji})]
|
||||
|
@ -356,7 +357,8 @@
|
|||
:community-id community-id
|
||||
:emoji emoji
|
||||
:edit-channel-id chat-id
|
||||
:category-id category-id})}
|
||||
:category-id category-id
|
||||
:position position})}
|
||||
(navigation/open-modal :edit-community-channel nil))))
|
||||
|
||||
(fx/defn community-created
|
||||
|
@ -564,6 +566,15 @@
|
|||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to remove chat from community" %)}]}))
|
||||
|
||||
(fx/defn delete-community-chat
|
||||
{:events [:delete-community-chat]}
|
||||
[_ community-id chat-id]
|
||||
{::json-rpc/call [{:method "wakuext_deleteCommunityChat"
|
||||
:params [community-id chat-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to delete community chat" %)}]})
|
||||
|
||||
(fx/defn delete-category
|
||||
{:events [:delete-community-category]}
|
||||
[_ community-id category-id]
|
||||
|
@ -592,6 +603,18 @@
|
|||
(navigation/navigate-back)
|
||||
(remove-chat-from-category community-id id categoryID))))
|
||||
|
||||
(fx/defn reorder-category-chat
|
||||
{:events [::reorder-community-category-chat]}
|
||||
[_ community-id category-id chat-id new-position]
|
||||
{::json-rpc/call [{:method "wakuext_reorderCommunityChat"
|
||||
:params [{:communityId community-id
|
||||
:categoryId category-id
|
||||
:chatId chat-id
|
||||
:position new-position}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to reorder community category chat" %)}]})
|
||||
|
||||
(fx/defn reorder-category
|
||||
{:events [::reorder-community-category]}
|
||||
[_ community-id category-id new-position]
|
||||
|
|
|
@ -165,6 +165,7 @@
|
|||
"wakuext_reorderCommunityChat" {}
|
||||
"wakuext_editCommunityCategory" {}
|
||||
"wakuext_deleteCommunityCategory" {}
|
||||
"wakuext_deleteCommunityChat" {}
|
||||
"wakuext_ensVerified" {}
|
||||
"wakuext_dismissActivityCenterNotifications" {}
|
||||
"wakuext_acceptActivityCenterNotifications" {}
|
||||
|
|
|
@ -876,6 +876,22 @@
|
|||
(assoc :color colors/blue))
|
||||
chats)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/sorted-categories-by-community-id
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:chats/by-community-id community-id])
|
||||
(re-frame/subscribe [:communities/community-chats community-id])])
|
||||
(fn [[chats comm-chats] [_ community-id]]
|
||||
(let [chat-cat (into {} (map (fn [{:keys [id categoryID position]}]
|
||||
{(str community-id id) {:categoryID categoryID
|
||||
:position position}})
|
||||
(vals comm-chats)))]
|
||||
(group-by :categoryID (sort-by :position
|
||||
(map #(cond-> (merge % (chat-cat (:chat-id %)))
|
||||
(= community-id constants/status-community-id)
|
||||
(assoc :color colors/blue))
|
||||
chats))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/category-by-chat-id
|
||||
(fn [[_ community-id _]]
|
||||
|
@ -902,7 +918,9 @@
|
|||
:<- [:communities]
|
||||
(fn [communities [_ id]]
|
||||
(->> (get-in communities [id :categories])
|
||||
(sort-by #(:position (get % 1))))))
|
||||
(map #(assoc (get % 1) :community-id id))
|
||||
(sort-by :position)
|
||||
(into []))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/current-chat-ui-props
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
(fn []
|
||||
(let [current-chat (<sub [:chat-by-id chat-id])
|
||||
{:keys [chat-name color description community-id emoji]} current-chat
|
||||
{:keys [position]} (<sub [:chats/community-chat-by-id community-id chat-id])
|
||||
category (<sub [:chats/category-by-chat-id community-id chat-id])
|
||||
{:keys [admin]} (<sub [:communities/community community-id])
|
||||
pinned-messages (<sub [:chats/pinned chat-id])]
|
||||
|
@ -27,7 +28,8 @@
|
|||
color
|
||||
emoji
|
||||
chat-id
|
||||
(:id category)])}])
|
||||
(:id category)
|
||||
position])}])
|
||||
:extended-header (profile-header/extended-header
|
||||
{:title chat-name
|
||||
:color color
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
[re-frame.core :as re-frame]
|
||||
[status-im.ui.screens.chat.sheets :as sheets]
|
||||
[status-im.ui.components.accordion :as accordion]
|
||||
[clojure.string :as string]
|
||||
[status-im.ui.screens.communities.styles :as styles]))
|
||||
|
||||
(def request-cooldown-ms (* 60 1000))
|
||||
|
@ -139,12 +138,6 @@
|
|||
:title (i18n/label :t/edit-chats)
|
||||
:accessibility-label :community-edit-chats
|
||||
:icon :main-icons/edit
|
||||
:on-press #(hide-sheet-and-dispatch [:open-modal :community-edit-chats {:community-id id}])}]
|
||||
[quo/list-item
|
||||
{:theme :accent
|
||||
:title (i18n/label :t/reorder-categories)
|
||||
:accessibility-label :community-reorder-categories
|
||||
:icon :main-icons/channel-category
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:open-modal :community-reorder-categories {:community-id id}])}]])]))
|
||||
|
||||
|
@ -168,46 +161,28 @@
|
|||
{:content (fn []
|
||||
[sheets/actions home-item])}])}])
|
||||
|
||||
(defn categories-accordion [community-id chats categories edit data]
|
||||
(defn categories-accordion [community-id chats categories data]
|
||||
[:<>
|
||||
(for [{:keys [name id state]} (vals categories)]
|
||||
(for [{:keys [name id state]} categories]
|
||||
^{:key (str "cat" name id)}
|
||||
[:<>
|
||||
[accordion/section
|
||||
{:on-open #(>evt [::communities/store-category-state community-id id true])
|
||||
:on-close #(>evt [::communities/store-category-state community-id id false])
|
||||
:default state
|
||||
:opened edit
|
||||
:disabled edit
|
||||
:title [rn/view styles/category-item
|
||||
(if edit
|
||||
[rn/touchable-opacity {:on-press #(>evt [:delete-community-category community-id id])}
|
||||
[icons/icon :main-icons/delete-circle {:no-color true}]]
|
||||
[icons/icon :main-icons/channel-category {:color colors/gray}])
|
||||
[icons/icon :main-icons/channel-category {:color colors/gray}]
|
||||
[rn/text {:style {:font-size 17 :margin-left 10 :color colors/black}} name]]
|
||||
:content [rn/view
|
||||
:content [:<>
|
||||
(for [chat (get chats id)]
|
||||
(if edit
|
||||
^{:key (str "chat" chat id)}
|
||||
[rn/view styles/category-item
|
||||
[rn/touchable-opacity {:on-press #(>evt [:remove-chat-from-community-category
|
||||
community-id
|
||||
(string/replace (:chat-id chat) community-id "")
|
||||
(:categoryID chat)])}
|
||||
[icons/icon :main-icons/delete-circle {:no-color true}]]
|
||||
[rn/view {:flex 1}
|
||||
[inner-item/home-list-item
|
||||
(assoc chat :public? true)]]]
|
||||
^{:key (str "chat" chat id)}
|
||||
[community-chat-item chat nil nil data]))]}]
|
||||
^{:key (str "chat" chat id)}
|
||||
[community-chat-item chat nil nil data])]}]
|
||||
[quo/separator]])])
|
||||
|
||||
(defn community-chat-list [community-id categories edit from-chat]
|
||||
(let [chats (<sub [:chats/categories-by-community-id community-id])]
|
||||
(defn community-chat-list [community-id categories from-chat]
|
||||
(let [chats (<sub [:chats/sorted-categories-by-community-id community-id])]
|
||||
(if (and (empty? categories) (empty? chats))
|
||||
(if edit
|
||||
[blank-page (i18n/label :t/welcome-community-blank-message-edit-chats)]
|
||||
[blank-page (i18n/label :t/welcome-community-blank-message)])
|
||||
[blank-page (i18n/label :t/welcome-community-blank-message)]
|
||||
[list/flat-list
|
||||
{:key-fn :chat-id
|
||||
:content-container-style {:padding-bottom 8}
|
||||
|
@ -215,7 +190,7 @@
|
|||
:data (get chats "")
|
||||
:render-data {:from-chat from-chat}
|
||||
:render-fn community-chat-item
|
||||
:header [categories-accordion community-id chats categories edit {:from-chat from-chat}]
|
||||
:header [categories-accordion community-id chats categories {:from-chat from-chat}]
|
||||
:footer [rn/view {:height 68}]}])))
|
||||
|
||||
(defn channel-preview-item [{:keys [id name]}]
|
||||
|
@ -267,23 +242,6 @@
|
|||
[components.react/small-loading-indicator]
|
||||
(i18n/label :t/fetch-community))]]]))
|
||||
|
||||
(defn community-edit []
|
||||
(let [{:keys [community-id]} (<sub [:get-screen-params])]
|
||||
(fn []
|
||||
(let [{:keys [id name images members permissions color]} (<sub [:communities/community community-id])
|
||||
categories (<sub [:communities/sorted-categories community-id])]
|
||||
[:<>
|
||||
[topbar/topbar
|
||||
{:modal? true
|
||||
:content [toolbar-content
|
||||
id
|
||||
name
|
||||
color
|
||||
images
|
||||
(not= (:access permissions) constants/community-no-membership-access)
|
||||
(count members)]}]
|
||||
[community-chat-list id categories true false]]))))
|
||||
|
||||
(defn community []
|
||||
(let [{:keys [community-id from-chat]} (<sub [:get-screen-params])]
|
||||
(fn []
|
||||
|
|
|
@ -65,4 +65,4 @@
|
|||
@category-name
|
||||
(vec @selected-items)]
|
||||
3000)}
|
||||
(i18n/label :t/create)]}]]))))
|
||||
(i18n/label :t/create)]}]]))))
|
||||
|
|
|
@ -1,60 +1,176 @@
|
|||
(ns status-im.ui.screens.communities.reorder-categories
|
||||
(:require [quo.core :as quo]
|
||||
[clojure.walk :as walk]
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[clojure.string :as string]
|
||||
[clojure.set :as clojure.set]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.constants :as constants]
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.components.topbar :as topbar]
|
||||
[status-im.communities.core :as communities]
|
||||
[status-im.utils.handlers :refer [>evt <sub]]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[status-im.ui.screens.communities.styles :as styles]
|
||||
[status-im.ui.screens.communities.community :as community]))
|
||||
[status-im.ui.screens.communities.community :as community]
|
||||
[status-im.ui.screens.home.views.inner-item :as inner-item]))
|
||||
|
||||
(defn category-change-positon [community-id key up? position]
|
||||
(let [new-position (if up? (dec position) (inc position))]
|
||||
(>evt [::communities/reorder-community-category community-id key new-position])))
|
||||
(def collapse-chats? (reagent/atom false))
|
||||
(def data (reagent/atom []))
|
||||
|
||||
(defn category-item-button [community-id up? disabled? key position]
|
||||
(let [[margin-right icon] (if up?
|
||||
[10 :main-icons/dropdown-up]
|
||||
[25 :main-icons/dropdown])]
|
||||
[react/touchable-opacity {:disabled disabled?
|
||||
:on-press #(category-change-positon
|
||||
community-id key up? position)}
|
||||
[rn/view {:style (styles/reorder-categories-button margin-right)}
|
||||
[icons/icon icon {:color colors/black}]]]))
|
||||
(defn show-delete-chat-confirmation [community-id chat-id]
|
||||
(utils/show-confirmation
|
||||
{:title (i18n/label :t/delete-confirmation)
|
||||
:content (i18n/label :t/delete-chat-confirmation)
|
||||
:confirm-button-text (i18n/label :t/delete)
|
||||
:on-accept #(>evt [:delete-community-chat community-id chat-id])}))
|
||||
|
||||
(defn category-item [community-id count {:keys [key name position]}]
|
||||
(let [up-disabled? (= position 0)
|
||||
down-disabled? (= position (dec count))]
|
||||
(defn show-delete-catgory-confirmation [community-id category-id]
|
||||
(utils/show-confirmation
|
||||
{:title (i18n/label :t/delete-confirmation)
|
||||
:content (i18n/label :t/delete-category-confirmation)
|
||||
:confirm-button-text (i18n/label :t/delete)
|
||||
:on-accept #(>evt [:delete-community-category community-id category-id])}))
|
||||
|
||||
(defn chat-item
|
||||
[{:keys [id community-id] :as home-item} is-active? drag]
|
||||
(let [chat-id (string/replace id community-id "")
|
||||
background-color (if is-active? colors/gray-lighter colors/white)
|
||||
home-item (clojure.set/rename-keys home-item {:id :chat-id})]
|
||||
[rn/view {:accessibility-label :chat-item
|
||||
:style (merge styles/category-item
|
||||
{:background-color background-color})}
|
||||
[rn/touchable-opacity
|
||||
{:accessibility-label :delete-community-chat
|
||||
:on-press #(show-delete-chat-confirmation community-id chat-id)}
|
||||
[icons/icon :main-icons/delete-circle {:no-color true}]]
|
||||
[rn/view {:flex 1}
|
||||
[inner-item/home-list-item (assoc home-item :edit? true) {:active-opacity 1}]]
|
||||
[rn/touchable-opacity {:on-long-press drag
|
||||
:delay-long-press 100
|
||||
:accessibility-label :chat-drag-handle
|
||||
:style {:padding 20}}
|
||||
[icons/icon :main-icons/reorder-handle {:no-color true :width 18 :height 12}]]]))
|
||||
|
||||
(defn category-item
|
||||
[{:keys [id name community-id]} is-active? drag]
|
||||
(let [background-color (if is-active? colors/gray-lighter colors/white)
|
||||
category-none? (string/blank? id)]
|
||||
[:<>
|
||||
[rn/view {:style styles/reorder-categories-item}
|
||||
[icons/icon :main-icons/channel-category {:color colors/gray}]
|
||||
[rn/text {:style (styles/reorder-categories-text)} name]
|
||||
[category-item-button community-id true up-disabled? key position]
|
||||
[category-item-button community-id false down-disabled? key position]]
|
||||
[quo/separator]]))
|
||||
[quo/separator]
|
||||
[rn/view {:accessibility-label :category-item
|
||||
:style (merge styles/category-item
|
||||
{:background-color background-color})}
|
||||
(if category-none?
|
||||
[icons/icon :main-icons/channel-category {:color colors/gray}]
|
||||
[rn/touchable-opacity
|
||||
{:accessibility-label :delete-category-button
|
||||
:on-press #(show-delete-catgory-confirmation community-id id)}
|
||||
[icons/icon :main-icons/delete-circle {:no-color true}]])
|
||||
[rn/view {:flex 1}
|
||||
[rn/text {:style {:font-size 17 :margin-left 10 :color colors/black}} name]]
|
||||
(when (and (not category-none?) @collapse-chats?)
|
||||
[rn/touchable-opacity {:accessibility-label :category-drag-handle
|
||||
:on-long-press drag
|
||||
:delay-long-press 100
|
||||
:style {:padding 20}}
|
||||
[icons/icon :main-icons/reorder-handle {:no-color true :width 18 :height 12}]])]]))
|
||||
|
||||
(defn categories-view [community-id categories count]
|
||||
[rn/view {:accessibility-label :reorder-categories-list}
|
||||
(for [category-vector categories]
|
||||
(let [category (clojure.set/rename-keys (get category-vector 1) {:id :key})]
|
||||
[category-item community-id count category]))])
|
||||
(defn render-fn
|
||||
[{:keys [chat-type] :as item} _ _ _ is-active? drag]
|
||||
(if (= chat-type constants/community-chat-type)
|
||||
[chat-item item is-active? drag]
|
||||
[category-item item is-active? drag]))
|
||||
|
||||
(defn calculate-chat-new-position-and-category
|
||||
[to second-call? old-category going-up?]
|
||||
(let [{:keys [id chat-type categoryID position]} (get @data to)
|
||||
[new-category new-position]
|
||||
(if going-up?
|
||||
(if (= chat-type constants/community-chat-type)
|
||||
[categoryID (if second-call? (inc position) position)]
|
||||
(if second-call? [id 0]
|
||||
(calculate-chat-new-position-and-category (dec to) true old-category true)))
|
||||
(if (= chat-type constants/community-chat-type)
|
||||
(if (= categoryID old-category)
|
||||
[categoryID position]
|
||||
[categoryID (inc position)]) [id 0]))]
|
||||
[new-category new-position]))
|
||||
|
||||
(defn update-local-atom [data-js]
|
||||
(reset! data data-js)
|
||||
(reagent/flush))
|
||||
|
||||
(defn on-drag-end-chat [from to data-js]
|
||||
(let [{:keys [id community-id categoryID position]} (get @data from)
|
||||
[new-category new-position] (calculate-chat-new-position-and-category
|
||||
to false categoryID (> from to))
|
||||
chat-id (string/replace id community-id "")]
|
||||
(when-not (and (= new-position position) (= new-category categoryID))
|
||||
(update-local-atom data-js)
|
||||
(>evt [::communities/reorder-community-category-chat
|
||||
community-id new-category chat-id new-position]))))
|
||||
|
||||
(defn on-drag-end-category [from to data-js]
|
||||
(let [{:keys [id community-id position]} (get @data from)]
|
||||
(when (and (< to (count @data)) (not= position to) (not= id ""))
|
||||
(update-local-atom data-js)
|
||||
(>evt [::communities/reorder-community-category community-id id to]))))
|
||||
|
||||
(defn on-drag-end-fn [from to data-js]
|
||||
(if @collapse-chats?
|
||||
(on-drag-end-category from to data-js)
|
||||
(when-not (= to 0) (on-drag-end-chat from to data-js))))
|
||||
|
||||
(defn reset-data [categories chats]
|
||||
(reset! data (if @collapse-chats? categories ;; If chats are collapsed then only show categories
|
||||
(walk/postwalk-replace ;; else, categories and chats
|
||||
{:chat-id :id}
|
||||
(reduce (fn [acc category]
|
||||
(-> acc
|
||||
(conj category)
|
||||
(into (get chats (:id category))))) [] categories)))))
|
||||
|
||||
(defn draggable-list []
|
||||
[rn/draggable-flat-list
|
||||
{:key-fn :id
|
||||
:data @data
|
||||
:render-fn render-fn
|
||||
:autoscroll-threshold (if platform/android? 150 250)
|
||||
:autoscroll-speed (if platform/android? 10 150) ;; TODO - Use same speed for both ios and android
|
||||
:container-style {:margin-bottom 108} ;; after bumping react native version to > 0.64
|
||||
:on-drag-end-fn on-drag-end-fn}])
|
||||
|
||||
(defn view []
|
||||
(let [{:keys [community-id]} (<sub [:get-screen-params])
|
||||
{:keys [id name images members permissions color]}
|
||||
(<sub [:communities/community community-id])
|
||||
categories (<sub [:communities/sorted-categories community-id])]
|
||||
sorted-categories (<sub [:communities/sorted-categories community-id])
|
||||
categories (if @collapse-chats? sorted-categories
|
||||
(conj sorted-categories
|
||||
{:id ""
|
||||
:position (count sorted-categories)
|
||||
:name (i18n/label :t/none)
|
||||
:community-id community-id}))
|
||||
chats (<sub [:chats/sorted-categories-by-community-id community-id])]
|
||||
(reset-data categories chats)
|
||||
[:<>
|
||||
[topbar/topbar
|
||||
{:modal? true
|
||||
:content [community/toolbar-content id name color images
|
||||
(not= (:access permissions) constants/community-no-membership-access)
|
||||
(count members)]}]
|
||||
(if (empty? categories)
|
||||
[community/blank-page (i18n/label :t/welcome-community-blank-message-categories)]
|
||||
[categories-view community-id categories (count categories)])]))
|
||||
(if (and (empty? sorted-categories) (empty? chats))
|
||||
[community/blank-page (i18n/label :t/welcome-community-blank-message-edit-chats)]
|
||||
[:<>
|
||||
[quo/list-item {:size :small
|
||||
:title (i18n/label :t/rearrange-categories)
|
||||
:active @collapse-chats?
|
||||
:accessory :switch
|
||||
:container-style {:padding-left 10}
|
||||
:on-press #(reset! collapse-chats? (not @collapse-chats?))}]
|
||||
[quo/separator]
|
||||
[draggable-list]])]))
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
(let [{:keys [community-id chat]} (<sub [:get-screen-params])]
|
||||
(fn []
|
||||
(let [categories (<sub [:communities/sorted-categories community-id])
|
||||
chats (<sub [:chats/sorted-categories-by-community-id community-id])
|
||||
comm-chat (<sub [:chats/community-chat-by-id community-id (:chat-id chat)])
|
||||
_ (reset! selected-item (:categoryID comm-chat))]
|
||||
[:<>
|
||||
|
@ -44,7 +45,7 @@
|
|||
:create-community-category
|
||||
{:community-id community-id}])
|
||||
:title (i18n/label :t/create-category)}]
|
||||
:data (conj (vec (vals categories)) {:name (i18n/label :t/none) :id ""})
|
||||
:data (conj categories {:name (i18n/label :t/none) :id ""})
|
||||
:render-fn render-fn}]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
|
@ -54,6 +55,7 @@
|
|||
[::communities/change-category-confirmation-pressed
|
||||
community-id
|
||||
@selected-item
|
||||
comm-chat]
|
||||
(assoc comm-chat :position
|
||||
(count (get chats @selected-item)))] ;; Add as last item in new category
|
||||
3000)}
|
||||
(i18n/label :t/done)]}]]))))
|
||||
|
|
|
@ -1,34 +1,8 @@
|
|||
(ns status-im.ui.screens.communities.styles
|
||||
(:require [quo.design-system.colors :as colors]))
|
||||
(ns status-im.ui.screens.communities.styles)
|
||||
|
||||
(def category-item
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:height 52
|
||||
:margin-left 18})
|
||||
|
||||
(def reorder-categories-item
|
||||
{:accessibility-label :reorder-categories-item
|
||||
:flex-direction :row
|
||||
:height 60
|
||||
:align-items :center
|
||||
:margin-left 18})
|
||||
|
||||
(defn reorder-categories-text []
|
||||
{:font-size 17
|
||||
:margin-left 10
|
||||
:color (colors/get-color :text-01)
|
||||
:flex 1})
|
||||
|
||||
(defn reorder-categories-button [margin-right]
|
||||
{:accessibility-label :reorder-categories-button
|
||||
:width 30
|
||||
:height 30
|
||||
:border-radius 15
|
||||
:margin 10
|
||||
:margin-right margin-right
|
||||
:border-width 1
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:border-color colors/black})
|
||||
:padding-left 18})
|
||||
|
|
|
@ -149,13 +149,16 @@
|
|||
:else
|
||||
[icons/icon :main-icons/tiny-new-contact (icon-style)]))
|
||||
|
||||
(defn chat-item-title [chat-id muted group-chat chat-name]
|
||||
(defn chat-item-title [chat-id muted group-chat chat-name edit?]
|
||||
[quo/text {:weight :medium
|
||||
:color (when muted :secondary)
|
||||
:accessibility-label :chat-name-text
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:style {:position :absolute :left 92 :top 10 :right 90}}
|
||||
:style {:position :absolute
|
||||
:left 92
|
||||
:top 10
|
||||
:right (if edit? 50 90)}}
|
||||
(if group-chat
|
||||
(utils/truncate-str chat-name 30)
|
||||
;; This looks a bit odd, but I would like only to subscribe
|
||||
|
@ -164,7 +167,7 @@
|
|||
(first @(re-frame/subscribe [:contacts/contact-two-names-by-identity chat-id])))])
|
||||
|
||||
(defn home-list-item [home-item opts]
|
||||
(let [{:keys [chat-id chat-name color group-chat public? timestamp last-message muted emoji highlight]} home-item
|
||||
(let [{:keys [chat-id chat-name color group-chat public? timestamp last-message muted emoji highlight edit?]} home-item
|
||||
background-color (when highlight (colors/get-color :interactive-02))]
|
||||
[react/touchable-opacity (merge {:style {:height 64 :background-color background-color}} opts)
|
||||
[:<>
|
||||
|
@ -178,13 +181,15 @@
|
|||
:default-chat-icon-text (if (string/blank? emoji)
|
||||
(chat-icon.styles/default-chat-icon-text 40)
|
||||
(chat-icon.styles/emoji-chat-icon-text 40))}]
|
||||
[chat-item-title chat-id muted group-chat chat-name]
|
||||
[react/text {:style styles/datetime-text
|
||||
:number-of-lines 1
|
||||
:accessibility-label :last-message-time-text}
|
||||
;;TODO (perf) move to event
|
||||
(memo-timestamp (if (pos? (:whisper-timestamp last-message))
|
||||
(:whisper-timestamp last-message)
|
||||
timestamp))]
|
||||
[message-content-text (select-keys last-message [:content :content-type :community-id]) true]
|
||||
[unviewed-indicator home-item]]]))
|
||||
[chat-item-title chat-id muted group-chat chat-name edit?]
|
||||
(when-not edit?
|
||||
[:<>
|
||||
[react/text {:style styles/datetime-text
|
||||
:number-of-lines 1
|
||||
:accessibility-label :last-message-time-text}
|
||||
;;TODO (perf) move to event
|
||||
(memo-timestamp (if (pos? (:whisper-timestamp last-message))
|
||||
(:whisper-timestamp last-message)
|
||||
timestamp))]
|
||||
[unviewed-indicator home-item]])
|
||||
[message-content-text (select-keys last-message [:content :content-type :community-id]) true]]]))
|
||||
|
|
|
@ -288,11 +288,6 @@
|
|||
;;TODO custom
|
||||
:options {:topBar {:visible false}}
|
||||
:component select-category/view}
|
||||
{:name :community-edit-chats
|
||||
;;TODO custom
|
||||
:insets {:bottom true}
|
||||
:options {:topBar {:visible false}}
|
||||
:component community/community-edit}
|
||||
{:name :community-reorder-categories
|
||||
:insets {:top false}
|
||||
:options {:topBar {:visible false}}
|
||||
|
|
|
@ -184,7 +184,7 @@
|
|||
"membership-request-pending": "Membership request pending",
|
||||
"create-community": "Create a community",
|
||||
"create-category": "Create category",
|
||||
"reorder-categories": "Reorder categories",
|
||||
"rearrange-categories": "Rearrange Categories",
|
||||
"edited": "Edited",
|
||||
"edit-community": "Edit community",
|
||||
"editing-message": "Editing message",
|
||||
|
@ -412,6 +412,7 @@
|
|||
"delete-bootnode-title": "Delete bootnode",
|
||||
"delete-chat": "Delete chat",
|
||||
"delete-chat-confirmation": "Are you sure you want to delete this chat?",
|
||||
"delete-category-confirmation": "Are you sure you want to delete this category?",
|
||||
"delete-confirmation": "Delete?",
|
||||
"delete-mailserver": "Delete Status node",
|
||||
"delete-mailserver-are-you-sure": "Are you sure you want to delete this Status node?",
|
||||
|
@ -1344,7 +1345,6 @@
|
|||
"welcome-blank-message": "Your chats will appear here. To start new chats press the ⊕ button",
|
||||
"welcome-community-blank-message": "Your channels will appear here. To create a new channel, click on the ⊕ button and select \"Create a channel\"",
|
||||
"welcome-community-blank-message-edit-chats": "Your channels will appear here. To create a new channel, go back to the community screen, click on the ⊕ button and select \"Create a channel\"",
|
||||
"welcome-community-blank-message-categories": "Your categories will appear here. To create a new category, go back to the community screen, click on the ⊕ button and select \"Create category\"",
|
||||
"welcome-blank-community-message": "Your communities will appear here.",
|
||||
"fetch-community": "Fetch community",
|
||||
"fetching-community": "Fetching community...",
|
||||
|
|
|
@ -6618,6 +6618,11 @@ 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-fast-image@8.5.11:
|
||||
version "8.5.11"
|
||||
resolved "https://registry.yarnpkg.com/react-native-fast-image/-/react-native-fast-image-8.5.11.tgz#e3dc969d0e4e8df026646bf18194465aa55cbc2b"
|
||||
|
|
Loading…
Reference in New Issue