diff --git a/.re-natal b/.re-natal index dd0e3cd390..40558f5bf9 100644 --- a/.re-natal +++ b/.re-natal @@ -13,7 +13,6 @@ }, "modules": [ "react-native-contacts", - "react-native-invertible-scroll-view", "awesome-phonenumber", "realm", "react-native-i18n", diff --git a/package-lock.json b/package-lock.json index bb1cae3a64..4cd9570297 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7586,17 +7586,6 @@ "resolved": "https://registry.npmjs.org/react-native-image-resizer/-/react-native-image-resizer-1.0.0.tgz", "integrity": "sha1-1H4UlDw3k44of71jnk23zrf9iRc=" }, - "react-native-invertible-scroll-view": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/react-native-invertible-scroll-view/-/react-native-invertible-scroll-view-1.1.0.tgz", - "integrity": "sha1-v9UKP11myhJjm3x6mETO3dHRaJA=", - "requires": { - "create-react-class": "15.6.2", - "prop-types": "15.6.0", - "react-clone-referenced-element": "1.0.1", - "react-native-scrollable-mixin": "1.0.1" - } - }, "react-native-level-fs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/react-native-level-fs/-/react-native-level-fs-3.0.0.tgz", diff --git a/react-native/src/status_im/react_native/js_dependencies.cljs b/react-native/src/status_im/react_native/js_dependencies.cljs index a2f77fd0e6..b7112caf74 100644 --- a/react-native/src/status_im/react_native/js_dependencies.cljs +++ b/react-native/src/status_im/react_native/js_dependencies.cljs @@ -19,7 +19,6 @@ (def image-crop-picker (js/require "react-native-image-crop-picker")) (def image-resizer (js/require "react-native-image-resizer")) (def instabug (js/require "instabug-reactnative")) -(def invertible-scroll-view (js/require "react-native-invertible-scroll-view")) (def linear-gradient (js/require "react-native-linear-gradient")) (def mapbox-gl (js/require "react-native-mapbox-gl")) (def nfc (js/require "nfc-react-native")) diff --git a/src/status_im/chat/new_chat/styles.cljs b/src/status_im/chat/new_chat/styles.cljs index a55a7f7878..67e1296372 100644 --- a/src/status_im/chat/new_chat/styles.cljs +++ b/src/status_im/chat/new_chat/styles.cljs @@ -6,5 +6,5 @@ :margin-bottom 0}) (def contacts-list - {:backgroundColor common/color-light-gray}) + {:background-color common/color-light-gray}) diff --git a/src/status_im/chat/new_chat/view.cljs b/src/status_im/chat/new_chat/view.cljs index 9d93d36470..bcfe690573 100644 --- a/src/status_im/chat/new_chat/view.cljs +++ b/src/status_im/chat/new_chat/view.cljs @@ -2,75 +2,72 @@ (:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require [re-frame.core :refer [dispatch]] [status-im.ui.components.common.common :as common] - [status-im.ui.components.renderers.renderers :as renderers] [status-im.ui.components.action-button.action-button :refer [action-button action-separator]] [status-im.ui.components.action-button.styles :refer [actions-list]] - [status-im.ui.components.react :refer [view text list-view list-item]] + [status-im.ui.components.list.views :as list] [status-im.ui.components.contact.contact :refer [contact-view]] + [status-im.ui.components.react :as react] [status-im.ui.components.status-bar.view :refer [status-bar]] [status-im.ui.components.toolbar.view :refer [toolbar-with-search]] - [status-im.ui.components.drawer.view :refer [drawer-view]] + [status-im.ui.components.drawer.view :as drawer] [status-im.chat.new-chat.styles :as styles] - [status-im.utils.listview :as lw] - [status-im.i18n :refer [label]])) + [status-im.i18n :as i18n])) (defn options-list [] - [view actions-list - [action-button {:label (label :t/new-group-chat) + [react/view actions-list + [action-button {:label (i18n/label :t/new-group-chat) :icon :icons/group-big :icon-opts {:color :blue} :on-press #(dispatch [:open-contact-toggle-list :chat-group])}] [action-separator] - [action-button {:label (label :t/new-public-group-chat) + [action-button {:label (i18n/label :t/new-public-group-chat) :icon :icons/public :icon-opts {:color :blue} :on-press #(dispatch [:navigate-to :new-public-chat])}] [action-separator] - [action-button {:label (label :t/add-new-contact) + [action-button {:label (i18n/label :t/add-new-contact) :icon :icons/add :icon-opts {:color :blue} :on-press #(dispatch [:navigate-to :new-contact])}]]) -(defn contact-list-row [] - (fn [row _ _] - (list-item ^{:key row} - [contact-view {:contact row - :on-press #(dispatch [:open-chat-with-contact %])}]))) +(defn contact-list-row [contact] + [contact-view {:contact contact + :on-press #(dispatch [:open-chat-with-contact %])}]) (defview new-chat-toolbar [] (letsubs [show-search [:get-in [:toolbar-search :show]] search-text [:get-in [:toolbar-search :text]]] - [view + [react/view [status-bar] (toolbar-with-search {:show-search? (= show-search :contact-list) :search-text search-text :search-key :contact-list - :title (label :t/contacts-group-new-chat) - :search-placeholder (label :t/search-for)})])) + :title (i18n/label :t/contacts-group-new-chat) + :search-placeholder (i18n/label :t/search-for)})])) + +(defn- header [contacts] + [react/view + [options-list] + [common/bottom-shadow] + [common/form-title (i18n/label :t/choose-from-contacts) + {:count-value (count contacts)}] + [common/list-header]]) (defview new-chat [] (letsubs [contacts [:all-added-group-contacts-filtered] params [:get :contacts/click-params]] - [drawer-view - [view styles/contacts-list-container + [drawer/drawer-view + [react/view styles/contacts-list-container [new-chat-toolbar] (when contacts - [list-view {:dataSource (lw/to-datasource contacts) - :enableEmptySections true - :renderRow (contact-list-row) - :bounces false - :keyboardShouldPersistTaps :always - :renderHeader #(list-item - [view - [options-list] - [common/bottom-shadow] - [common/form-title (label :t/choose-from-contacts) - {:count-value (count contacts)}] - [common/list-header]]) - :renderSeparator renderers/list-separator-renderer - :renderFooter #(list-item [view - [common/list-footer] - [common/bottom-shadow]]) - :style styles/contacts-list}])]])) + [list/flat-list {:style styles/contacts-list + :data contacts + :render-fn contact-list-row + :bounces false + :keyboardShouldPersistTaps :always + :header (header contacts) + :footer [react/view + [common/list-footer] + [common/bottom-shadow]]}])]])) diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index b5e9ccf9eb..a86732a129 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -1,16 +1,10 @@ (ns status-im.chat.screen (:require-macros [status-im.utils.views :refer [defview letsubs]]) - (:require [re-frame.core :as re-frame] - [status-im.ui.components.react :as react] - [status-im.ui.components.icons.vector-icons :as vector-icons] - [status-im.ui.components.status-bar.view :as status-bar] - [status-im.ui.components.chat-icon.screen :as chat-icon-screen] + (:require [clojure.string :as string] + [re-frame.core :as re-frame] [status-im.chat.styles.screen :as style] - [status-im.utils.listview :as listview] [status-im.utils.datetime :as time] [status-im.utils.platform :as platform] - [status-im.ui.components.invertible-scroll-view :as scroll-view] - [status-im.ui.components.toolbar.view :as toolbar] [status-im.chat.views.toolbar-content :as toolbar-content] [status-im.chat.views.message.message :as message] [status-im.chat.views.message.datemark :as message-datemark] @@ -18,9 +12,15 @@ [status-im.chat.views.actions :as actions] [status-im.chat.views.bottom-info :as bottom-info] [status-im.i18n :as i18n] + [status-im.ui.components.react :as react] + [status-im.ui.components.list.views :as list] + [status-im.ui.components.icons.vector-icons :as vector-icons] + [status-im.ui.components.status-bar.view :as status-bar] + [status-im.ui.components.chat-icon.screen :as chat-icon-screen] + [status-im.ui.components.animation :as anim] [status-im.ui.components.animation :as anim] [status-im.ui.components.sync-state.offline :as offline] - [clojure.string :as string])) + [status-im.ui.components.toolbar.view :as toolbar])) (defview chat-icon [] (letsubs [{:keys [chat-id group-chat name color]} [:get-current-chat]] @@ -65,26 +65,25 @@ (defmethod message-row :datemark [{{:keys [value]} :row}] - (react/list-item [message-datemark/chat-datemark value])) + [message-datemark/chat-datemark value]) (defmethod message-row :default [{:keys [group-chat current-public-key row]}] - (react/list-item [message/chat-message (assoc row - :group-chat group-chat - :current-public-key current-public-key)])) + [message/chat-message (assoc row + :group-chat group-chat + :current-public-key current-public-key)]) (defview messages-view [chat-id group-chat] (letsubs [messages [:get-chat-messages chat-id] current-public-key [:get-current-public-key]] - [react/list-view {:renderRow (fn [row _ index] - (message-row {:group-chat group-chat - :current-public-key current-public-key - :row row})) - :renderScrollComponent #(scroll-view/invertible-scroll-view (js->clj %)) - :onEndReached #(re-frame/dispatch [:load-more-messages]) - :enableEmptySections true - :keyboardShouldPersistTaps (if platform/android? :always :handled) - :dataSource (listview/to-datasource-inverted messages)}])) + [list/flat-list {:data messages + :render-fn #(message-row {:group-chat group-chat + :current-public-key current-public-key + :row %1}) + :inverted true + :onEndReached #(re-frame/dispatch [:load-more-messages]) + :enableEmptySections true + :keyboardShouldPersistTaps (if platform/android? :always :handled)}])) (defview chat [] (letsubs [{:keys [chat-id group-chat input-text]} [:get-current-chat] diff --git a/src/status_im/chat/views/api/choose_contact.cljs b/src/status_im/chat/views/api/choose_contact.cljs index a49f6120a3..eee96181c6 100644 --- a/src/status_im/chat/views/api/choose_contact.cljs +++ b/src/status_im/chat/views/api/choose_contact.cljs @@ -1,40 +1,33 @@ (ns status-im.chat.views.api.choose-contact (:require-macros [status-im.utils.views :refer [defview]]) - (:require [reagent.core :as r] - [re-frame.core :refer [dispatch subscribe]] - [status-im.ui.components.react :refer [view - text - list-view - list-item]] + (:require [re-frame.core :as re-frame] [status-im.ui.components.contact.contact :refer [contact-view]] - [status-im.ui.components.renderers.renderers :as renderers] - [status-im.utils.listview :as lw])) + [status-im.ui.components.list.views :as list] + [status-im.ui.components.react :as react])) -(defn render-row [arg-index bot-db-key] - (fn [contact _ _] - (list-item - ^{:key contact} - [contact-view {:contact contact - :on-press #(dispatch +(defn- render-contact [arg-index bot-db-key] + (fn [contact] + [contact-view {:contact contact + :on-press #(re-frame/dispatch [:set-contact-as-command-argument {:arg-index arg-index :bot-db-key bot-db-key - :contact contact}])}]))) + :contact contact}])}])) + (defview choose-contact-view [{title :title arg-index :index bot-db-key :bot-db-key}] [contacts [:contacts-filtered :people-in-current-chat]] - [view {:flex 1} - [text {:style {:font-size 14 - :color "rgb(147, 155, 161)" - :padding-top 12 - :padding-left 16 - :padding-right 16 - :padding-bottom 12}} + [react/view {:flex 1} + [react/text {:style {:font-size 14 + :color "rgb(147, 155, 161)" + :padding-top 12 + :padding-left 16 + :padding-right 16 + :padding-bottom 12}} title] - [list-view {:dataSource (lw/to-datasource contacts) - :enableEmptySections true - :renderRow (render-row arg-index bot-db-key) - :bounces false - :keyboardShouldPersistTaps :always - :renderSeparator renderers/list-separator-renderer}]]) + [list/flat-list {:data contacts + :render-fn (render-contact arg-index bot-db-key) + :enableEmptySections true + :keyboardShouldPersistTaps :always + :bounces false}]]) diff --git a/src/status_im/chat/views/bottom_info.cljs b/src/status_im/chat/views/bottom_info.cljs index 5417af4db7..094487fcba 100644 --- a/src/status_im/chat/views/bottom_info.cljs +++ b/src/status_im/chat/views/bottom_info.cljs @@ -1,23 +1,15 @@ (ns status-im.chat.views.bottom-info (:require-macros [status-im.utils.views :refer [defview]]) - (:require [re-frame.core :refer [subscribe dispatch]] - [reagent.core :as r] - [status-im.ui.components.react :refer [view - animated-view - image - text - icon - touchable-highlight - list-view - list-item]] - [status-im.ui.components.chat-icon.screen :refer [chat-icon-view-menu-item]] - [status-im.chat.styles.screen :as st] - [status-im.i18n :refer [label label-pluralize message-status-label]] + (:require [re-frame.core :as re-frame] + [reagent.core :as reagent] + [clojure.string :as string] + [status-im.ui.components.react :as react] + [status-im.chat.styles.screen :as styles] + [status-im.i18n :as i18n] [status-im.ui.components.animation :as anim] - [status-im.utils.utils :refer [truncate-str]] - [status-im.utils.identicon :refer [identicon]] - [status-im.utils.listview :as lw] - [clojure.string :as str])) + [status-im.ui.components.list.views :as list] + [status-im.utils.utils :as utils] + [status-im.utils.identicon :as identicon])) (defn- container-animation-logic [{:keys [to-value val]}] (fn [_] @@ -26,50 +18,50 @@ :friction 6 :tension 40})))) -(defn overlay [{:keys [on-click-outside]} items] - [view {:style st/bottom-info-overlay} - [touchable-highlight {:on-press on-click-outside - :style st/overlay-highlight} - [view nil]] +(defn- overlay [{:keys [on-click-outside]} items] + [react/view styles/bottom-info-overlay + [react/touchable-highlight {:on-press on-click-outside + :style styles/overlay-highlight} + [react/view nil]] items]) -(defn container [height & _] +(defn- container [height & _] (let [anim-value (anim/create-value 1) context {:to-value height :val anim-value} on-update (container-animation-logic context)] - (r/create-class + (reagent/create-class {:component-did-update on-update :display-name "container" :reagent-render (fn [height & children] - [animated-view {:style (st/bottom-info-container height)} - (into [view] children)])}))) + [react/animated-view {:style (styles/bottom-info-container height)} + (into [react/view] children)])}))) -(defn message-status-row [{:keys [photo-path name]} {:keys [whisper-identity status]}] - [view st/bottom-info-row - [image {:source {:uri (or photo-path (identicon whisper-identity))} - :style st/bottom-info-row-photo}] - [view st/bottom-info-row-text-container - [text {:style st/bottom-info-row-text1 - :number-of-lines 1} - (truncate-str (if-not (str/blank? name) - name - whisper-identity) 30)] - [text {:style st/bottom-info-row-text2 - :number-of-lines 1} - (message-status-label (or status :sending))]]]) +(defn- message-status-row [{:keys [photo-path name]} {:keys [whisper-identity status]}] + [react/view styles/bottom-info-row + [react/image {:source {:uri (or photo-path (identicon/identicon whisper-identity))} + :style styles/bottom-info-row-photo}] + [react/view styles/bottom-info-row-text-container + [react/text {:style styles/bottom-info-row-text1 + :number-of-lines 1} + (utils/truncate-str (if-not (string/blank? name) + name + whisper-identity) 30)] + [react/text {:style styles/bottom-info-row-text2 + :number-of-lines 1} + (i18n/message-status-label (or status :sending))]]]) -(defn render-row [contacts] +(defn- render-status [contacts] (fn [{:keys [whisper-identity] :as row} _ _] (let [contact (get contacts whisper-identity)] - (list-item [message-status-row contact row])))) + [message-status-row contact row]))) (defn bottom-info-view [] - (let [bottom-info (subscribe [:get-current-chat-ui-prop :bottom-info]) - contacts (subscribe [:get-contacts])] - (r/create-class + (let [bottom-info (re-frame/subscribe [:get-current-chat-ui-prop :bottom-info]) + contacts (re-frame/subscribe [:get-contacts])] + (reagent/create-class {:display-name "bottom-info-view" :reagent-render (fn [] @@ -80,9 +72,9 @@ :status message-status}])) (into {})) statuses (vals (merge participants user-statuses))] - [overlay {:on-click-outside #(dispatch [:set-chat-ui-props {:show-bottom-info? false}])} - [container (* st/item-height (count statuses)) - [list-view {:dataSource (lw/to-datasource statuses) - :enableEmptySections true - :renderRow (render-row @contacts) - :contentContainerStyle st/bottom-info-list-container}]]]))}))) + [overlay {:on-click-outside #(re-frame/dispatch [:set-chat-ui-props {:show-bottom-info? false}])} + [container (* styles/item-height (count statuses)) + [list/flat-list {:contentContainerStyle styles/bottom-info-list-container + :data statuses + :render-fn (render-status @contacts) + :enableEmptySections true}]]]))}))) \ No newline at end of file diff --git a/src/status_im/chat/views/input/validation_messages.cljs b/src/status_im/chat/views/input/validation_messages.cljs index 26c5dc1a0c..e7f9f24fdf 100644 --- a/src/status_im/chat/views/input/validation_messages.cljs +++ b/src/status_im/chat/views/input/validation_messages.cljs @@ -1,20 +1,19 @@ (ns status-im.chat.views.input.validation-messages (:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require [re-frame.core :as re-frame] - [status-im.ui.components.react :as c] + [status-im.ui.components.react :as react] [status-im.chat.styles.input.validation-message :as style] - [status-im.utils.listview :as lw] [status-im.i18n :as i18n])) (defn validation-message [{:keys [title description]}] - [c/view style/message-container - [c/text {:style style/message-title} + [react/view style/message-container + [react/text {:style style/message-title} title] - [c/text {:style style/message-description} + [react/text {:style style/message-description} description]]) -(defn messages-list [markup] - [c/view {:flex 1} +(defn- messages-list [markup] + [react/view {:flex 1} markup]) (defview validation-messages-view [] @@ -22,7 +21,7 @@ input-height [:get-current-chat-ui-prop :input-height] messages [:validation-messages]] (when messages - [c/view (style/root (+ input-height chat-input-margin)) + [react/view (style/root (+ input-height chat-input-margin)) (if (string? messages) [messages-list [validation-message {:title (i18n/label :t/error) :description messages}]] diff --git a/src/status_im/ui/components/drawer/view.cljs b/src/status_im/ui/components/drawer/view.cljs index f20c1fdad7..8c6e7c21de 100644 --- a/src/status_im/ui/components/drawer/view.cljs +++ b/src/status_im/ui/components/drawer/view.cljs @@ -1,30 +1,19 @@ (ns status-im.ui.components.drawer.view (:require-macros [status-im.utils.views :refer [defview letsubs]]) - (:require [cljs.spec.alpha :as s] - [clojure.string :as str] - [reagent.core :as r] - [re-frame.core :as rf] + (:require [clojure.string :as string] + [reagent.core :as reagent] + [re-frame.core :as re-frame] [status-im.ui.components.chat-icon.screen :as ci] [status-im.ui.components.common.common :as common] [status-im.ui.components.context-menu :as context-menu] [status-im.ui.components.drawer.styles :as st] - [status-im.ui.components.react :refer [view - text - text-input - list-item - list-view - drawer-layout - touchable-without-feedback - touchable-highlight - touchable-opacity - dismiss-keyboard!]] + [status-im.ui.components.react :as react] [status-im.ui.components.icons.vector-icons :as vi] [status-im.ui.components.status-view.view :as status-view] [status-im.i18n :as i18n] [status-im.ui.screens.profile.db :as profile.db] [status-im.utils.datetime :as time] [status-im.utils.gfycat.core :as gfycat] - [status-im.utils.listview :as lw] [status-im.utils.platform :as platform] [status-im.utils.utils :as utils] [status-im.utils.money :as money] @@ -39,26 +28,26 @@ ;; editing the name or status field (defn save-profile! [] - (when-let [save-event @(rf/subscribe [:my-profile.drawer/save-event])] - (rf/dispatch [save-event]))) + (when-let [save-event @(re-frame/subscribe [:my-profile.drawer/save-event])] + (re-frame/dispatch [save-event]))) (defn navigate-to-profile [] (close-drawer!) (save-profile!) - (rf/dispatch [:navigate-to :my-profile])) + (re-frame/dispatch [:navigate-to :my-profile])) (defn navigate-to-accounts [] (close-drawer!) (save-profile!) ;; TODO(rasom): probably not the best place for this call (protocol/stop-whisper!) - (rf/dispatch [:navigate-to :accounts])) + (re-frame/dispatch [:navigate-to :accounts])) (defview profile-picture [] (letsubs [account [:get-current-account]] - [touchable-opacity {:on-press navigate-to-profile - :style st/user-photo-container} - [view + [react/touchable-opacity {:on-press navigate-to-profile + :style st/user-photo-container} + [react/view [ci/chat-icon (:photo-path account) {:size 52 :accessibility-label :drawer-profile-icon}]]])) @@ -66,88 +55,79 @@ (letsubs [profile-name [:my-profile.drawer/get :name] valid-name? [:my-profile.drawer/valid-name?] placeholder [:get :my-profile/default-name]] - [view st/name-input-wrapper - [text-input + [react/view st/name-input-wrapper + [react/text-input {:placeholder placeholder :style (st/name-input-text valid-name?) :font :medium - :default-value profile-name - :on-focus #(rf/dispatch [:my-profile.drawer/edit-name]) - :on-change-text #(rf/dispatch [:my-profile.drawer/update-name %]) - :on-end-editing #(rf/dispatch [:my-profile.drawer/save-name])}]])) + :default-value profile-name + :on-focus #(re-frame/dispatch [:my-profile.drawer/edit-name]) + :on-change-text #(re-frame/dispatch [:my-profile.drawer/update-name %]) + :on-end-editing #(re-frame/dispatch [:my-profile.drawer/save-name])}]])) (defview status-input [] (letsubs [edit-status? [:my-profile.drawer/get :edit-status?] status [:my-profile.drawer/get :status]] (let [placeholder (i18n/label :t/update-status)] - [view st/status-container + [react/view st/status-container (if edit-status? - [text-input {:style st/status-input-view - :multiline true - :auto-focus true - :focus edit-status? - :max-length 140 - :accessibility-label :drawer-status-input - :placeholder placeholder - :default-value status - :on-change-text #(rf/dispatch [:my-profile.drawer/update-status %]) - :on-end-editing #(when edit-status? - (rf/dispatch [:my-profile.drawer/save-status]))}] - - [status-view/status-view {:style (st/status-view (str/blank? status)) + [react/text-input {:style st/status-input-view + :multiline true + :auto-focus true + :focus edit-status? + :max-length 140 + :accessibility-label :drawer-status-input + :placeholder placeholder + :default-value status + :on-change-text #(re-frame/dispatch [:my-profile.drawer/update-status %]) + :on-end-editing #(when edit-status? + (re-frame/dispatch [:my-profile.drawer/save-status]))}] + [status-view/status-view {:style (st/status-view (string/blank? status)) :number-of-lines 3 - :status (if (str/blank? status) + :status (if (string/blank? status) placeholder status) - :on-press #(rf/dispatch [:my-profile.drawer/edit-status])}])]))) - -(defn render-separator-fn [transactions-count] - (fn [_ row-id _] - (when (< row-id (dec transactions-count)) - (list-item - ^{:key row-id} - [common/separator {} st/transactions-list-separator])))) + :on-press #(re-frame/dispatch [:my-profile.drawer/edit-status])}])]))) (defview current-network [] (letsubs [network [:get-current-account-network]] - [view {:style st/network-label-container} - [text {:style st/network-label} (i18n/label :t/current-network)] - [text {:style st/network-title} (:name network)]])) + [react/view {:style st/network-label-container} + [react/text {:style st/network-label} (i18n/label :t/current-network)] + [react/text {:style st/network-title} (:name network)]])) (defn options-btn [] - [view {:style st/options-button} - [touchable-highlight - {:on-press navigate-to-profile} - [view [vi/icon :icons/options]]]]) + [react/view {:style st/options-button} + [react/touchable-highlight {:on-press navigate-to-profile} + [react/view [vi/icon :icons/options]]]]) (defn switch-account [] - [view st/switch-account-container - [touchable-highlight + [react/view st/switch-account-container + [react/touchable-highlight {:on-press navigate-to-accounts} - [view - [text {:style st/switch-account-text - :font (if platform/android? :medium :default) - :uppercase? platform/android?} + [react/view + [react/text {:style st/switch-account-text + :font (if platform/android? :medium :default) + :uppercase? platform/android?} (i18n/label :t/switch-users)]]]]) (defn drawer [] (fn [] - [touchable-without-feedback {:on-press #(dismiss-keyboard!)} - [view st/drawer - [view st/upper-container - [view st/profile-container + [react/touchable-without-feedback {:on-press #(react/dismiss-keyboard!)} + [react/view st/drawer + [react/view st/upper-container + [react/view st/profile-container [profile-picture] [name-input] [status-input] [options-btn]] [current-network]] - [view + [react/view [switch-account]]]])) (defn drawer-view [items] - [drawer-layout {:drawerWidth 300 - :renderNavigationView #(r/as-element [drawer]) - :onDrawerSlide dismiss-keyboard! - :ref (fn [drawer] - (reset! drawer-atom drawer))} + [react/drawer-layout {:drawerWidth 300 + :renderNavigationView #(reagent/as-element [drawer]) + :onDrawerSlide react/dismiss-keyboard! + :ref (fn [drawer] + (reset! drawer-atom drawer))} items]) diff --git a/src/status_im/ui/components/invertible_scroll_view.cljs b/src/status_im/ui/components/invertible_scroll_view.cljs index 1f4722353f..e69de29bb2 100644 --- a/src/status_im/ui/components/invertible_scroll_view.cljs +++ b/src/status_im/ui/components/invertible_scroll_view.cljs @@ -1,8 +0,0 @@ -(ns status-im.ui.components.invertible-scroll-view - (:require [reagent.core :as r] - [status-im.react-native.js-dependencies :as rn-dependencies])) - -(defn invertible-scroll-view [props] - (r/create-element rn-dependencies/invertible-scroll-view - (clj->js (merge {:inverted true} props)))) - diff --git a/src/status_im/ui/components/list/styles.cljs b/src/status_im/ui/components/list/styles.cljs index f6d83f67df..8023a29bb6 100644 --- a/src/status_im/ui/components/list/styles.cljs +++ b/src/status_im/ui/components/list/styles.cljs @@ -62,6 +62,10 @@ base-separator {:margin-left 70})) +(defstyle list-header-footer-spacing + {:android {:background-color styles/color-white + :height 8}}) + (defstyle section-separator (merge base-separator {:android {:margin-top 12} diff --git a/src/status_im/ui/components/list/views.cljs b/src/status_im/ui/components/list/views.cljs index 71c628d65d..12965494a7 100644 --- a/src/status_im/ui/components/list/views.cljs +++ b/src/status_im/ui/components/list/views.cljs @@ -18,129 +18,147 @@ [section-list {:sections [{:title \"\" :key :unik :render-fn render :data {:title \"\" :subtitle \"\"}}]}] " - (:require [reagent.core :as r] - [status-im.ui.components.list.styles :as lst] + (:require [reagent.core :as reagent] + [reagent.impl.template :as temp] + [status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.checkbox.view :as checkbox] - [status-im.ui.components.react :as rn] - [status-im.ui.components.icons.vector-icons :as vi] - [status-im.utils.platform :as p])) + [status-im.ui.components.list.styles :as styles] + [status-im.ui.components.react :as react] + [status-im.utils.platform :as platform])) -(def flat-list-class (rn/get-class "FlatList")) -(def section-list-class (rn/get-class "SectionList")) +(def flat-list-class (react/get-class "FlatList")) +(def section-list-class (react/get-class "SectionList")) (defn item ([content] (item nil content)) ([left-action content] (item left-action content nil)) ([left-action content right-action] - [rn/view {:style lst/item} - [rn/view {:style lst/left-item-wrapper} + [react/view {:style styles/item} + [react/view {:style styles/left-item-wrapper} left-action] - [rn/view {:style lst/content-item-wrapper} + [react/view {:style styles/content-item-wrapper} content] (when right-action - [rn/view {:style lst/right-item-wrapper} + [react/view {:style styles/right-item-wrapper} right-action])])) (defn touchable-item [handler item] - [rn/touchable-highlight {:on-press handler} + [react/touchable-highlight {:on-press handler} item]) (defn item-icon [{:keys [icon style icon-opts]}] - [rn/view {:style style} - [vi/icon icon (merge icon-opts {:style lst/item-icon})]]) + [react/view {:style style} + [vector-icons/icon icon (merge icon-opts {:style styles/item-icon})]]) (defn item-image - [{:keys [source style]}] - [rn/view {:style style} - [rn/image {:source source - :style lst/item-image}]]) + [{:keys[source style]}] + [react/view {:style style} + [react/image {:source source + :style styles/item-image}]]) (defn item-primary [primary] - [rn/text {:style lst/primary-text} primary]) + [react/text {:style styles/primary-text} primary]) (defn item-primary-only [primary] - [rn/text {:style lst/primary-text-only} primary]) + [react/text {:style styles/primary-text-only} primary]) (defn item-secondary [secondary] - [rn/text {:style lst/secondary-text :ellipsize-mode "middle" :number-of-lines 1} secondary]) + [react/text {:style styles/secondary-text :ellipsize-mode :middle :number-of-lines 1} secondary]) (defn item-content [& children] - (into [rn/view {:style lst/item-text-view}] (keep identity children))) + (into [react/view {:style styles/item-text-view}] (keep identity children))) (defn item-checkbox [{:keys [style] :as props}] - [rn/view {:style (merge style lst/item-checkbox)} + [react/view {:style (merge style styles/item-checkbox)} [checkbox/checkbox props]]) (defn- wrap-render-fn [f] (fn [data] - ;; For details on passed data - ;; https://facebook.github.io/react-native/docs/sectionlist.html#renderitem - (let [{:keys [item index separators]} (js->clj data :keywordize-keys true)] - (r/as-element (f (js->clj item) index separators))))) + (reagent/as-element (f (.-item data) (.-index data) (.-separators data))))) -(defn- separator [] - [rn/view lst/separator]) +(def default-separator [react/view styles/separator]) -(defn- section-separator [] - [rn/view lst/section-separator]) +(def default-header [react/view styles/list-header-footer-spacing]) -(defn- base-list-props [render-fn empty-component separator?] - (merge {:keyExtractor (fn [_ i] i)} - (when render-fn {:renderItem (wrap-render-fn render-fn)}) - (when (and p/ios? separator?) {:ItemSeparatorComponent (fn [] (r/as-element [separator]))}) - ;; TODO(jeluard) Does not work with our current ReactNative version - (when empty-component {:ListEmptyComponent (r/as-element [empty-component])}))) +(def default-footer [react/view styles/list-header-footer-spacing]) + +(def section-separator [react/view styles/section-separator]) + +(defn- base-list-props + [{:keys [render-fn empty-component header separator default-separator?]}] + (let [separator (or separator (when (and platform/ios? default-separator?) default-separator))] + (merge {:keyExtractor (fn [_ i] i)} + (when render-fn {:renderItem (wrap-render-fn render-fn)}) + (when separator {:ItemSeparatorComponent (fn [] (reagent/as-element [separator]))}) + (when empty-component {:ListEmptyComponent (fn [] (reagent/as-element empty-component))}) + (when header {:ListHeaderComponent (fn [] (reagent/as-element header))})))) + +;; Workaround an issue in reagent that does not consider JS array as JS value +;; This forces clj <-> js serialization and breaks clj semantic +;; See https://github.com/reagent-project/reagent/issues/335 + +(deftype Item [value] + IEncodeJS + (-clj->js [x] (.-value x)) + (-key->js [x] (.-value x)) + IEncodeClojure + (-js->clj [x options] (.-value x))) + +(defn- to-js-array + "Converts a collection to a JS array (but leave content as is)" + [coll] + (let [arr (array)] + (doseq [x coll] + (.push arr x)) + arr)) + +(defn- wrap-data [o] + (Item. (to-js-array o))) (defn flat-list "A wrapper for FlatList. See https://facebook.github.io/react-native/docs/flatlist.html" - [{:keys [data render-fn empty-component separator?] :as props - :or {separator? true}}] + [{:keys [data empty-component] :as props}] {:pre [(or (nil? data) (sequential? data))]} - (if (and (empty? data) empty-component) - ;; TODO(jeluard) remove when native :ListEmptyComponent is supported - empty-component - [flat-list-class - (merge (base-list-props render-fn empty-component separator?) - {:data (clj->js data)} - props)])) + [flat-list-class + (merge (base-list-props props) + props + {:data (wrap-data data)})]) (defn- wrap-render-section-header-fn [f] (fn [data] - ;; For details on passed data - ;; https://facebook.github.io/react-native/docs/sectionlist.html#rendersectionheader - (let [{:keys [section]} (js->clj data :keywordize-keys true)] - (r/as-element (f section))))) + (reagent/as-element (f (.-section data))))) (defn- default-render-section-header [{:keys [title data]}] (when (seq data) - [rn/text {:style lst/section-header} + [react/text {:style styles/section-header} title])) (defn- wrap-per-section-render-fn [props] - ;; TODO(jeluard) Somehow wrapping `:render-fn` does not work - (if-let [f (:render-fn props)] - (assoc (dissoc props :render-fn) :renderItem (wrap-render-fn f)) - props)) + (update + (if-let [f (:render-fn props)] + (assoc (dissoc props :render-fn) :renderItem (wrap-render-fn f)) + props) + :data wrap-data)) (defn section-list "A wrapper for SectionList. See https://facebook.github.io/react-native/docs/sectionlist.html" - [{:keys [sections render-fn empty-component render-section-header-fn separator?] :as props - :or {render-section-header-fn default-render-section-header - separator? true}}] + [{:keys [sections empty-component render-section-header-fn] :as props + :or {render-section-header-fn default-render-section-header}}] (if (and (every? #(empty? (:data %)) sections) empty-component) empty-component [section-list-class - (merge (base-list-props render-fn empty-component separator?) + (merge (base-list-props props) + props {:sections (clj->js (map wrap-per-section-render-fn sections)) :renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)} - (when p/ios? {:SectionSeparatorComponent (fn [] (r/as-element [section-separator]))}) - props)])) + (when platform/ios? {:SectionSeparatorComponent (fn [] (reagent/as-element [section-separator]))}))])) + diff --git a/src/status_im/ui/components/react.cljs b/src/status_im/ui/components/react.cljs index 15211c2365..f9c633f3e6 100644 --- a/src/status_im/ui/components/react.cljs +++ b/src/status_im/ui/components/react.cljs @@ -1,6 +1,7 @@ (ns status-im.ui.components.react (:require-macros [status-im.utils.views :as views]) - (:require [reagent.core :as r] + (:require [clojure.string :as string] + [reagent.core :as r] [status-im.ui.components.styles :as st] [status-im.utils.utils :as u] [status-im.utils.platform :refer [platform-specific ios?]] @@ -40,7 +41,6 @@ (def status-bar (get-class "StatusBar")) (def drawer-layout (adapt-class (.-default drawer))) -(def list-view-class (get-class "ListView")) (def scroll-view (get-class "ScrollView")) (def web-view (get-class "WebView")) (def keyboard-avoiding-view-class (get-class "KeyboardAvoidingView")) @@ -82,7 +82,7 @@ ([{:keys [uppercase?] :as opts} t & ts] (r/as-element (let [ts (cond->> (conj ts t) - uppercase? (map clojure.string/upper-case))] + uppercase? (map #(when % (string/upper-case %))))] (vec (concat [text-class (add-font-style :style opts)] ts)))))) @@ -106,11 +106,6 @@ :resizeMode "contain" :style style}])) -;; TODO Migrate to new FlatList and SectionList when appropriate (see components.list). ListView will eventually get deprecated -;; see https://facebook.github.io/react-native/docs/using-a-listview.html -(defn list-view [props] - [list-view-class (merge {:enableEmptySections true} props)]) - (defn touchable-highlight [props content] [touchable-highlight-class (merge {:underlay-color :transparent} props) diff --git a/src/status_im/ui/components/renderers/renderers.cljs b/src/status_im/ui/components/renderers/renderers.cljs index f9a4f2a848..e69de29bb2 100644 --- a/src/status_im/ui/components/renderers/renderers.cljs +++ b/src/status_im/ui/components/renderers/renderers.cljs @@ -1,14 +0,0 @@ -(ns status-im.ui.components.renderers.renderers - (:require [status-im.ui.components.react :refer [list-item]] - [status-im.ui.components.common.common :as common])) - -(defn list-separator-renderer [_ row-id _] - (list-item - ^{:key row-id} - [common/list-separator])) - -(defn list-header-renderer [& _] - (list-item [common/list-header])) - -(defn list-footer-renderer [& _] - (list-item [common/list-footer])) diff --git a/src/status_im/ui/screens/accounts/views.cljs b/src/status_im/ui/screens/accounts/views.cljs index 2c89ff7f65..9d779da7fb 100644 --- a/src/status_im/ui/screens/accounts/views.cljs +++ b/src/status_im/ui/screens/accounts/views.cljs @@ -1,60 +1,56 @@ (ns status-im.ui.screens.accounts.views (:require-macros [status-im.utils.views :refer [defview]]) - (:require [re-frame.core :refer [dispatch dispatch-sync]] - [status-im.ui.screens.accounts.styles :as st] - [status-im.ui.components.status-bar.view :refer [status-bar]] + (:require [clojure.string :as string] + [re-frame.core :as re-frame] + [status-im.ui.screens.accounts.styles :as styles] + [status-im.ui.components.list.views :as list] + [status-im.ui.components.status-bar.view :as status-bar] [status-im.ui.components.toolbar.actions :as act] [status-im.ui.components.common.common :as common] [status-im.ui.components.action-button.action-button :refer [action-button]] - [status-im.utils.listview :as lw] [status-im.constants :refer [console-chat-id]] - [status-im.ui.components.react :refer [view - text - list-view - list-item - image - touchable-highlight]] - [status-im.i18n :as i18n] - [clojure.string :as str])) + [status-im.ui.components.react :as react] + [status-im.i18n :as i18n])) + (defn account-badge [address photo-path name] - [view st/account-badge - [image {:source {:uri (if (str/blank? photo-path) :avatar photo-path)} - :style st/photo-image}] - [view st/account-badge-text-view - [text {:style st/account-badge-text - :numberOfLines 1} + [react/view styles/account-badge + [react/image {:source {:uri (if (string/blank? photo-path) :avatar photo-path)} + :style styles/photo-image}] + [react/view styles/account-badge-text-view + [react/text {:style styles/account-badge-text + :numberOfLines 1} (or name address)]]]) (defn account-view [{:keys [address photo-path name] :as account}] - [view - [touchable-highlight {:on-press #(dispatch [:open-login address photo-path name])} - [view st/account-view + [react/view + [react/touchable-highlight {:on-press #(re-frame/dispatch [:open-login address photo-path name])} + [react/view styles/account-view [account-badge address photo-path name]]]]) (defview accounts [] [accounts [:get-accounts]] - [view st/accounts-container - [status-bar {:type :transparent}] - [view st/account-title-conatiner - [text {:style st/account-title-text - :font :toolbar-title} + [react/view styles/accounts-container + [status-bar/status-bar {:type :transparent}] + [react/view styles/account-title-conatiner + [react/text {:style styles/account-title-text + :font :toolbar-title} (i18n/label :t/sign-in-to-status)]] - [view st/accounts-list-container - [list-view {:dataSource (lw/to-datasource (vals accounts)) - :renderSeparator #(list-item ^{:key %2} [view {:height 10}]) - :renderRow #(list-item [account-view %])}]] - [view st/bottom-actions-container + [react/view styles/accounts-list-container + [list/flat-list {:data (vals accounts) + :render-fn (fn [account] [account-view account]) + :separator [react/view {:height 10}]}]] + [react/view styles/bottom-actions-container [action-button (merge {:label (i18n/label :t/create-new-account) :icon :icons/add :icon-opts {:color :white} - :on-press #(dispatch [:create-new-account-handler])} - st/accounts-action-button)] - [common/separator st/accounts-separator st/accounts-separator-wrapper] + :on-press #(re-frame/dispatch [:create-new-account-handler])} + styles/accounts-action-button)] + [common/separator styles/accounts-separator styles/accounts-separator-wrapper] [action-button (merge {:label (i18n/label :t/recover-access) :icon :icons/dots-horizontal :icon-opts {:color :white} - :on-press #(dispatch [:navigate-to :recover])} - st/accounts-action-button)]]]) + :on-press #(re-frame/dispatch [:navigate-to :recover])} + styles/accounts-action-button)]]]) diff --git a/src/status_im/ui/screens/chats_list/views.cljs b/src/status_im/ui/screens/chats_list/views.cljs index b53db8334d..59b0140210 100644 --- a/src/status_im/ui/screens/chats_list/views.cljs +++ b/src/status_im/ui/screens/chats_list/views.cljs @@ -2,7 +2,7 @@ (:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require [re-frame.core :as re-frame] [status-im.ui.components.common.common :as common] - [status-im.ui.components.renderers.renderers :as renderers] + [status-im.ui.components.list.views :as list] [status-im.ui.components.react :as react] [status-im.ui.components.native-action-button :refer [native-action-button]] [status-im.ui.components.drawer.view :as drawer] @@ -15,7 +15,6 @@ [status-im.ui.components.sync-state.offline :refer [offline-view]] [status-im.ui.components.context-menu :refer [context-menu]] [status-im.ui.components.tabs.styles :refer [tabs-height]] - [status-im.utils.listview :refer [to-datasource]] [status-im.ui.screens.chats-list.views.inner-item :as inner-item] [status-im.ui.screens.chats-list.styles :as st] [status-im.i18n :as i18n] @@ -84,18 +83,17 @@ edit? [toolbar-edit] (= show-search :chat-list) [toolbar-search] :else [toolbar-view]) - [react/list-view {:dataSource (to-datasource chats) - :renderRow (fn [[id :as row] _ _] - (react/list-item ^{:key id} [chat-list-item row edit?])) - :renderHeader (when-not (empty? chats) renderers/list-header-renderer) - :renderFooter (when-not (empty? chats) - #(react/list-item [react/view - [common/list-footer] - [common/bottom-shadow]])) - :renderSeparator renderers/list-separator-renderer - :style st/list-container}] + [list/flat-list {:style st/list-container + :data chats + :render-fn (fn [chat] [chat-list-item chat edit?]) + :header (when-not (empty? chats) list/default-header) + :footer (when-not (empty? chats) + [react/view + [common/list-footer] + [common/bottom-shadow]])}] + (when (and (not edit?) - (not= show-search :chat-list) + (not= show-search :chat-list) (get-in platform-specific [:chats :action-button?])) [chats-action-button]) [offline-view]])) diff --git a/src/status_im/ui/screens/contacts/contact_list/views.cljs b/src/status_im/ui/screens/contacts/contact_list/views.cljs index d2e070f1f6..523a381a7d 100644 --- a/src/status_im/ui/screens/contacts/contact_list/views.cljs +++ b/src/status_im/ui/screens/contacts/contact_list/views.cljs @@ -1,34 +1,32 @@ (ns status-im.ui.screens.contacts.contact-list.views (:require-macros [status-im.utils.views :refer [defview letsubs]]) - (:require [re-frame.core :refer [dispatch]] - [status-im.ui.components.renderers.renderers :as renderers] - [status-im.ui.components.contact.contact :refer [contact-view]] - [status-im.ui.screens.contacts.views :refer [contact-options]] - [status-im.ui.components.react :refer [view list-view list-item]] - [status-im.ui.components.status-bar.view :refer [status-bar]] + (:require [re-frame.core :as re-frame] + [status-im.ui.components.contact.contact :as contact-view] + [status-im.ui.components.list.views :as list] + [status-im.ui.components.react :as react] + [status-im.ui.components.status-bar.view :as status-bar] [status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.components.toolbar.actions :as act] - [status-im.ui.components.drawer.view :refer [drawer-view]] - [status-im.ui.screens.contacts.styles :as st] - [status-im.utils.listview :as lw] - [status-im.i18n :refer [label]])) + [status-im.ui.components.drawer.view :as drawer-view] + [status-im.ui.screens.contacts.styles :as styles] + [status-im.ui.screens.contacts.views :as contact-options] + [status-im.i18n :as i18n])) + (defn render-row [group edit?] (fn [row _ _] - (list-item - ^{:key row} - [contact-view {:contact row - :on-press #(dispatch [:open-chat-with-contact %]) - :extended? edit? - :extend-options (contact-options row group)}]))) + [contact-view/contact-view {:contact row + :on-press #(re-frame/dispatch [:open-chat-with-contact %]) + :extended? edit? + :extend-options (contact-options/contact-options row group)}])) (defview contact-list-toolbar-edit [group] [toolbar/toolbar {} - [toolbar/nav-button (act/back #(dispatch [:set-in [:contacts/list-ui-props :edit?] false]))] + [toolbar/nav-button (act/back #(re-frame/dispatch [:set-in [:contacts/list-ui-props :edit?] false]))] [toolbar/content-title (if-not group - (label :t/contacts) - (or (:name group) (label :t/contacts-group-new-chat)))]]) + (i18n/label :t/contacts) + (or (:name group) (i18n/label :t/contacts-group-new-chat)))]]) (defview contact-list-toolbar [group] (letsubs [show-search [:get-in [:toolbar-search :show]] @@ -38,30 +36,29 @@ :search-text search-text :search-key :contact-list :title (if-not group - (label :t/contacts) - (or (:name group) (label :t/contacts-group-new-chat))) - :search-placeholder (label :t/search-contacts) - :actions [(act/opts [{:text (label :t/edit) - :value #(dispatch [:set-in [:contacts/list-ui-props :edit?] true])}])]}))) + (i18n/label :t/contacts) + (or (:name group) (i18n/label :t/contacts-group-new-chat))) + :search-placeholder (i18n/label :t/search-contacts) + :actions [(act/opts [{:text (i18n/label :t/edit) + :value #(re-frame/dispatch [:set-in [:contacts/list-ui-props :edit?] true])}])]}))) (defview contacts-list-view [group edit?] (letsubs [contacts [:all-added-group-contacts-filtered (:group-id group)]] - [list-view {:dataSource (lw/to-datasource contacts) - :enableEmptySections true - :renderRow (render-row group edit?) - :keyboardShouldPersistTaps :always - :renderHeader renderers/list-header-renderer - :renderFooter renderers/list-footer-renderer - :renderSeparator renderers/list-separator-renderer - :style st/contacts-list}])) + [list/flat-list {:style styles/contacts-list + :data contacts + :render-fn (render-row group edit?) + :enableEmptySections true + :keyboardShouldPersistTaps :always + :header list/default-header + :footer list/default-footer}])) (defview contact-list [] (letsubs [edit? [:get-in [:contacts/list-ui-props :edit?]] group [:get-contact-group]] - [drawer-view - [view {:flex 1} - [view - [status-bar] + [drawer-view/drawer-view + [react/view {:flex 1} + [react/view + [status-bar/status-bar] (if edit? [contact-list-toolbar-edit group] [contact-list-toolbar group])] diff --git a/src/status_im/ui/screens/contacts/contact_list_modal/views.cljs b/src/status_im/ui/screens/contacts/contact_list_modal/views.cljs index 4db7f796a6..0172906b6e 100644 --- a/src/status_im/ui/screens/contacts/contact_list_modal/views.cljs +++ b/src/status_im/ui/screens/contacts/contact_list_modal/views.cljs @@ -2,18 +2,17 @@ (:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require [re-frame.core :refer [dispatch]] [status-im.ui.components.common.common :as common] - [status-im.ui.components.renderers.renderers :as renderers] - [status-im.ui.components.react :refer [view list-view list-item]] [status-im.ui.components.contact.contact :refer [contact-view]] [status-im.ui.components.action-button.action-button :refer [action-button action-separator]] [status-im.ui.components.action-button.styles :refer [actions-list]] + [status-im.ui.components.list.views :as list] + [status-im.ui.components.react :as react] [status-im.ui.components.status-bar.view :refer [status-bar]] [status-im.ui.components.toolbar.view :refer [toolbar-with-search]] [status-im.ui.components.drawer.view :refer [drawer-view]] [status-im.ui.screens.contacts.styles :as st] - [status-im.utils.listview :as lw] - [status-im.i18n :refer [label]])) + [status-im.i18n :as i18n])) (defview contact-list-modal-toolbar [] (letsubs [show-search [:get-in [:toolbar-search :show]] @@ -23,13 +22,13 @@ :show-search? (= show-search :contact-list) :search-text search-text :search-key :contact-list - :title (label :t/contacts) - :search-placeholder (label :t/search-contacts)}))) + :title (i18n/label :t/contacts) + :search-placeholder (i18n/label :t/search-contacts)}))) (defn actions-view [action click-handler] - [view actions-list + [react/view actions-list [action-button - {:label (label :t/enter-address) + {:label (i18n/label :t/enter-address) :icon :icons/address :icon-opts {:color :blue} :on-press #(do @@ -38,22 +37,21 @@ (dispatch [:navigate-back]))}] [action-separator] (if (= :request action) - [action-button {:label (label :t/show-qr) + [action-button {:label (i18n/label :t/show-qr) :icon :icons/qr :icon-opts {:color :blue} :on-press #(click-handler :qr-scan action)}] - [action-button {:label (label :t/scan-qr) + [action-button {:label (i18n/label :t/scan-qr) :icon :icons/fullscreen :icon-opts {:color :blue} :on-press #(click-handler :qr-scan action)}])]) (defn render-row [click-handler action params] (fn [row _ _] - (list-item - ^{:key row} - [contact-view {:contact row - :on-press #(when click-handler - (click-handler row action params))}]))) + [contact-view {:contact row + :on-press #(when click-handler + (click-handler row action params))}])) + (defview contact-list-modal [] (letsubs [contacts [:contacts-filtered :all-added-people-contacts] @@ -61,24 +59,22 @@ action [:get :contacts/click-action] params [:get :contacts/click-params]] [drawer-view - [view {:flex 1} + [react/view {:flex 1} [status-bar {:type :modal-white}] [contact-list-modal-toolbar] - [list-view {:dataSource (lw/to-datasource contacts) - :enableEmptySections true - :renderRow (render-row click-handler action params) - :bounces false - :keyboardShouldPersistTaps :always - :renderHeader (when-not (:hide-actions? params) - #(list-item - [view - [actions-view action click-handler] - [common/bottom-shadow] - [common/form-title (label :t/choose-from-contacts) - {:count-value (count contacts)}] - [common/list-header]])) - :renderFooter #(list-item [view - [common/list-footer] - [common/bottom-shadow]]) - :renderSeparator renderers/list-separator-renderer - :style st/contacts-list-modal}]]])) + [list/flat-list {:style st/contacts-list-modal + :data contacts + :render-fn (render-row click-handler action params) + :header (when-not (:hide-actions? params) + [react/view + [actions-view action click-handler] + [common/bottom-shadow] + [common/form-title (i18n/label :t/choose-from-contacts) + {:count-value (count contacts)}] + [common/list-header]]) + :footer [react/view + [common/list-footer] + [common/bottom-shadow]] + :enableEmptySections true + :bounces false + :keyboardShouldPersistTaps :always}]]])) diff --git a/src/status_im/ui/screens/discover/all_dapps/views.cljs b/src/status_im/ui/screens/discover/all_dapps/views.cljs index 3fae265e1a..daf0224eeb 100644 --- a/src/status_im/ui/screens/discover/all_dapps/views.cljs +++ b/src/status_im/ui/screens/discover/all_dapps/views.cljs @@ -40,7 +40,7 @@ [list/flat-list {:data (vals dapps) :render-fn render-dapp :horizontal true - :separator? false + :default-separator? false :shows-horizontal-scroll-indicator false :content-container-style styles/dapp-preview-flat-list}] [react/text (i18n/label :t/none)])]) diff --git a/src/status_im/ui/screens/discover/popular_hashtags/views.cljs b/src/status_im/ui/screens/discover/popular_hashtags/views.cljs index 0736ba0547..79f0bc330d 100644 --- a/src/status_im/ui/screens/discover/popular_hashtags/views.cljs +++ b/src/status_im/ui/screens/discover/popular_hashtags/views.cljs @@ -22,7 +22,7 @@ :render-fn render-tag :horizontal true :shows-horizontal-scroll-indicator false - :separator? false}]]) + :default-separator? false}]]) (defview discover-all-hashtags [] (letsubs [current-account [:get-current-account] diff --git a/src/status_im/ui/screens/discover/search_results/views.cljs b/src/status_im/ui/screens/discover/search_results/views.cljs index 0b8e3a3cbd..8c325b8e74 100644 --- a/src/status_im/ui/screens/discover/search_results/views.cljs +++ b/src/status_im/ui/screens/discover/search_results/views.cljs @@ -2,11 +2,11 @@ (:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require [status-im.ui.components.react :as react] [status-im.ui.components.icons.vector-icons :as vi] + [status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.screens.discover.components.views :as components] [status-im.i18n :as i18n] [status-im.ui.screens.discover.styles :as styles] - [status-im.ui.screens.contacts.styles :as contacts-styles] - [status-im.ui.components.toolbar.view :as toolbar])) + [status-im.ui.screens.contacts.styles :as contacts-styles])) ;; TOOD(oskarth): Refactor this, very similar to discover-all-hashtags view (defview discover-search-results [] diff --git a/src/status_im/ui/screens/group/add_contacts/views.cljs b/src/status_im/ui/screens/group/add_contacts/views.cljs index 4d493f138f..230a0982d8 100644 --- a/src/status_im/ui/screens/group/add_contacts/views.cljs +++ b/src/status_im/ui/screens/group/add_contacts/views.cljs @@ -1,24 +1,26 @@ (ns status-im.ui.screens.group.add-contacts.views (:require-macros [status-im.utils.views :refer [defview letsubs]]) - (:require [re-frame.core :refer [dispatch]] - [status-im.ui.components.renderers.renderers :as renderers] + (:require [re-frame.core :as re-frame] + [status-im.ui.components.contact.contact :refer [toogle-contact-view]] + [status-im.ui.components.list.views :as list] [status-im.ui.components.react :as react] [status-im.ui.components.sticky-button :refer [sticky-button]] [status-im.ui.components.status-bar.view :refer [status-bar]] [status-im.ui.components.toolbar.view :refer [toolbar-with-search]] - [status-im.utils.listview :refer [to-datasource]] [status-im.ui.screens.group.styles :as styles] + [status-im.ui.screens.contacts.styles :as contacts.styles] + [status-im.i18n :as i18n] [status-im.ui.screens.contacts.styles :as cstyles] [status-im.i18n :refer [label]] [status-im.ui.components.contact.contact :refer [toogle-contact-view]])) (defn on-toggle [checked? whisper-identity] (let [action (if checked? :deselect-contact :select-contact)] - (dispatch [action whisper-identity]))) + (re-frame/dispatch [action whisper-identity]))) (defn on-toggle-participant [checked? whisper-identity] (let [action (if checked? :deselect-participant :select-participant)] - (dispatch [action whisper-identity]))) + (re-frame/dispatch [action whisper-identity]))) (defn group-toggle-contact [{:keys [whisper-identity] :as contact}] [toogle-contact-view contact :is-contact-selected? on-toggle]) @@ -45,19 +47,16 @@ :search-text search-text :search-key :contact-group-list :custom-title (title-with-count title contacts-count) - :search-placeholder (label :t/search-contacts)}))) + :search-placeholder (i18n/label :t/search-contacts)}))) (defn toggle-list [contacts render-function] [react/view {:flex 1} - [react/list-view - {:dataSource (to-datasource contacts) - :renderRow (fn [row _ _] - (react/list-item ^{:key row} [render-function row])) - :renderSeparator renderers/list-separator-renderer - :renderFooter renderers/list-footer-renderer - :renderHeader renderers/list-header-renderer - :style cstyles/contacts-list - :keyboardShouldPersistTaps :always}]]) + [list/flat-list {:style contacts.styles/contacts-list + :data contacts + :render-fn (fn [contact] [render-function contact]) + :footer list/default-footer + :header list/default-header + :keyboardShouldPersistTaps :always}]]) (defview contact-toggle-list [] (letsubs [contacts [:all-added-group-contacts-filtered] @@ -66,13 +65,13 @@ [react/keyboard-avoiding-view {:style styles/group-container} [status-bar] [toggle-list-toolbar - (label (if (= group-type :contact-group) - :t/new-group - :t/new-group-chat)) + (i18n/label (if (= group-type :contact-group) + :t/new-group + :t/new-group-chat)) selected-contacts-count] [toggle-list contacts group-toggle-contact] (when (pos? selected-contacts-count) - [sticky-button (label :t/next) #(dispatch [:navigate-to :new-group])])])) + [sticky-button (i18n/label :t/next) #(re-frame/dispatch [:navigate-to :new-group])])])) (defview add-contacts-toggle-list [] (letsubs [contacts [:all-group-not-added-contacts-filtered] @@ -83,9 +82,9 @@ [toggle-list-toolbar (:name group) selected-contacts-count] [toggle-list contacts group-toggle-contact] (when (pos? selected-contacts-count) - [sticky-button (label :t/save) #(do - (dispatch [:add-selected-contacts-to-group]) - (dispatch [:navigate-back]))])])) + [sticky-button (i18n/label :t/save) #(do + (re-frame/dispatch [:add-selected-contacts-to-group]) + (re-frame/dispatch [:navigate-back]))])])) (defview add-participants-toggle-list [] (letsubs [contacts [:contacts-filtered :all-new-contacts] @@ -96,6 +95,6 @@ [toggle-list-toolbar chat-name selected-contacts-count] [toggle-list contacts group-toggle-participant] (when (pos? selected-contacts-count) - [sticky-button (label :t/save) #(do - (dispatch [:add-new-group-chat-participants]) - (dispatch [:navigate-back]))])])) + [sticky-button (i18n/label :t/save) #(do + (re-frame/dispatch [:add-new-group-chat-participants]) + (re-frame/dispatch [:navigate-back]))])])) diff --git a/src/status_im/ui/screens/group/edit_contacts/views.cljs b/src/status_im/ui/screens/group/edit_contacts/views.cljs index c7c37fa417..31f561137e 100644 --- a/src/status_im/ui/screens/group/edit_contacts/views.cljs +++ b/src/status_im/ui/screens/group/edit_contacts/views.cljs @@ -1,14 +1,13 @@ (ns status-im.ui.screens.group.edit-contacts.views (:require-macros [status-im.utils.views :refer [defview letsubs]]) - (:require [re-frame.core :refer [dispatch]] + (:require [re-frame.core :as re-frame] [status-im.ui.components.contact.contact :refer [contact-view]] - [status-im.ui.components.renderers.renderers :as renderers] - [status-im.ui.components.react :refer [view list-view list-item]] + [status-im.ui.components.list.views :as list] + [status-im.ui.components.react :as react] [status-im.ui.components.status-bar.view :refer [status-bar]] [status-im.ui.components.toolbar.view :refer [toolbar-with-search]] - [status-im.utils.listview :refer [to-datasource]] [status-im.ui.screens.group.styles :as styles] - [status-im.i18n :refer [label]])) + [status-im.i18n :as i18n])) (defview contact-list-toolbar [title] (letsubs [show-search [:get-in [:toolbar-search :show]] @@ -18,35 +17,33 @@ :search-text search-text :search-key :contact-list :title title - :search-placeholder (label :t/search-contacts)}))) + :search-placeholder (i18n/label :t/search-contacts)}))) (defn contacts-list [contacts extended? extend-options] - [view {:flex 1} - [list-view {:dataSource (to-datasource contacts) - :enableEmptySections true - :renderRow (fn [row _ _] - (list-item - ^{:key row} - [contact-view {:contact row - :extended? extended? - :extend-options (extend-options row)}])) - :bounces false - :keyboardShouldPersistTaps :always - :renderSeparator renderers/list-separator-renderer - :renderFooter renderers/list-footer-renderer - :renderHeader renderers/list-header-renderer}]]) + [react/view {:flex 1} + [list/flat-list {:data contacts + :enableEmptySections true + :renderRow (fn [contact] + [contact-view {:contact contact + :extended? extended? + :extend-options (extend-options contact)}]) + + :bounces false + :keyboardShouldPersistTaps :always + :footer list/default-footer + :header list/default-header}]]) (defn chat-extended-options [item] - [{:value #(dispatch [:remove-group-chat-participants #{(:whisper-identity item)}]) - :text (label :t/remove)}]) + [{:value #(re-frame/dispatch [:remove-group-chat-participants #{(:whisper-identity item)}]) + :text (i18n/label :t/remove)}]) (defn contact-extended-options [group-id] (fn [item] - [{:value #(dispatch [:remove-contact-from-group - (:whisper-identity item) - group-id]) + [{:value #(re-frame/dispatch [:remove-contact-from-group + (:whisper-identity item) + group-id]) :accessibility-label :remove-button - :text (label :t/remove-from-group)}])) + :text (i18n/label :t/remove-from-group)}])) (defview edit-chat-group-contact-list [] (letsubs [chat-name [:chat :name] @@ -54,7 +51,7 @@ current-pk [:get :current-public-key] group-admin [:chat :group-admin]] (let [admin? (= current-pk group-admin)] - [view styles/group-container + [react/view styles/group-container [status-bar] [contact-list-toolbar chat-name] [contacts-list @@ -71,7 +68,7 @@ (defview edit-contact-group-contact-list [] (letsubs [group [:get-contact-group]] - [view styles/group-container + [react/view styles/group-container [status-bar] [contact-list-toolbar (:name group)] [contacts-list-view (:group-id group)]])) diff --git a/src/status_im/ui/screens/group/views.cljs b/src/status_im/ui/screens/group/views.cljs index 36059afbd1..9ba02f275d 100644 --- a/src/status_im/ui/screens/group/views.cljs +++ b/src/status_im/ui/screens/group/views.cljs @@ -5,15 +5,14 @@ [status-im.ui.components.common.common :as common] [status-im.ui.components.action-button.action-button :refer [action-button action-separator]] [status-im.ui.components.react :refer [view text touchable-highlight - keyboard-avoiding-view list-view list-item]] + keyboard-avoiding-view]] [status-im.ui.components.icons.vector-icons :as vi] + [status-im.ui.components.list.views :as list] [status-im.ui.components.text-input-with-label.view :refer [text-input-with-label]] [status-im.ui.components.status-bar.view :refer [status-bar]] [status-im.ui.components.toolbar.view :as toolbar] [status-im.utils.platform :refer [platform-specific ios?]] [status-im.ui.components.sticky-button :refer [sticky-button]] - [status-im.utils.listview :refer [to-datasource]] - [status-im.ui.components.renderers.renderers :as renderers] [status-im.ui.components.contact.contact :refer [contact-view]] [status-im.ui.screens.group.styles :as styles] [status-im.i18n :refer [label]] @@ -139,10 +138,9 @@ (when save-btn-enabled? [sticky-button (label :t/save) #(dispatch [:set-contact-group-name])])]))) -(defn render-row [row _ _] - (list-item - ^{:key row} - [contact-view {:contact row}])) +(defn- render-contact [contact] + [contact-view {:contact contact}]) + (defview new-group [] (letsubs [contacts [:selected-group-contacts] @@ -154,12 +152,11 @@ [group-toolbar group-type false] [group-name-view] [view styles/list-view-container - [list-view {:dataSource (to-datasource contacts) - :enableEmptySections true - :renderRow render-row - :bounces false - :keyboardShouldPersistTaps :always - :renderSeparator renderers/list-separator-renderer}]] + [list/flat-list {:data contacts + :render-fn render-contact + :bounces false + :keyboardShouldPersistTaps :always + :enableEmptySections true}]] (when save-btn-enabled? [sticky-button (label :t/save) (if (= group-type :contact-group) diff --git a/src/status_im/ui/screens/network_settings/views.cljs b/src/status_im/ui/screens/network_settings/views.cljs index 837d8b33d7..fa2dcf8f53 100644 --- a/src/status_im/ui/screens/network_settings/views.cljs +++ b/src/status_im/ui/screens/network_settings/views.cljs @@ -1,31 +1,29 @@ (ns status-im.ui.screens.network-settings.views (:require-macros [status-im.utils.views :as views]) - (:require - [status-im.utils.listview :as lw] - [re-frame.core :as rf] - [status-im.ui.components.status-bar.view :as status-bar] - [status-im.ui.components.toolbar.view :as toolbar] - [status-im.ui.components.action-button.action-button :as action-button] - [status-im.ui.components.action-button.styles :as action-button-styles] - [status-im.ui.components.react :as react] - [status-im.ui.components.icons.vector-icons :as vi] - [status-im.ui.components.common.common :as common] - [status-im.ui.components.renderers.renderers :as renderers] - [status-im.ui.screens.network-settings.styles :as st] - [status-im.i18n :as i18n])) + (:require [re-frame.core :as re-frame] + [status-im.ui.components.action-button.action-button :as action-button] + [status-im.ui.components.action-button.styles :as action-button-styles] + [status-im.ui.components.react :as react] + [status-im.ui.components.icons.vector-icons :as vector-icons] + [status-im.ui.components.list.views :as list] + [status-im.ui.components.common.common :as common] + [status-im.ui.screens.network-settings.styles :as styles] + [status-im.ui.components.status-bar.view :as status-bar] + [status-im.ui.components.toolbar.view :as toolbar] + [status-im.i18n :as i18n])) (defn network-icon [connected? size] - [react/view (st/network-icon connected? size) - [vi/icon :icons/network {:color (if connected? :white :gray)}]]) + [react/view (styles/network-icon connected? size) + [vector-icons/icon :icons/network {:color (if connected? :white :gray)}]]) (defn network-badge [& [{:keys [name connected? options]}]] - [react/view st/network-badge + [react/view styles/network-badge [network-icon connected? 56] [react/view {:padding-left 16} - [react/text {:style st/badge-name-text} + [react/text {:style styles/badge-name-text} (or name (i18n/label :t/new-network))] (when connected? - [react/text {:style st/badge-connected-text} + [react/text {:style styles/badge-connected-text} (i18n/label :t/connected)])]]) (defn actions-view [] @@ -43,21 +41,19 @@ {:text (i18n/label :t/paste-json-as-text) :value #(dispatch [:navigate-to :paste-json-text])} {:text (i18n/label :t/specify-rpc-url) :value #(dispatch [:navigate-to :add-rpc-url])}]]]) -(defn render-row [current-network] - (fn [{:keys [id name config] :as row} _ _] +(defn render-network [current-network] + (fn [{:keys [id name config] :as network}] (let [connected? (= id current-network)] - (react/list-item - ^{:key row} - [react/touchable-highlight - {:on-press #(rf/dispatch [:navigate-to :network-details row])} - [react/view st/network-item - [network-icon connected? 40] - [react/view {:padding-horizontal 16} - [react/text {:style st/network-item-name-text} - name] - (when connected? - [react/text {:style st/network-item-connected-text} - (i18n/label :t/connected)])]]])))) + [react/touchable-highlight + {:on-press #(re-frame/dispatch [:navigate-to :network-details network])} + [react/view styles/network-item + [network-icon connected? 40] + [react/view {:padding-horizontal 16} + [react/text {:style styles/network-item-name-text} + name] + (when connected? + [react/text {:style styles/network-item-connected-text} + (i18n/label :t/connected)])]]]))) (views/defview network-settings [] (views/letsubs [{:keys [network networks]} [:get-current-account]] @@ -66,17 +62,15 @@ [toolbar/simple-toolbar (i18n/label :t/network-settings)] [react/view {:flex 1} - [react/list-view {:dataSource (lw/to-datasource (vals networks)) - :renderRow (render-row network) - :renderHeader #(react/list-item - [react/view - [actions-view] - [common/bottom-shadow] - [common/form-title (i18n/label :t/existing-networks) - {:count-value (count networks)}] - [common/list-header]]) - :renderFooter #(react/list-item [react/view - [common/list-footer] - [common/bottom-shadow]]) - :renderSeparator renderers/list-separator-renderer - :style st/networks-list}]]])) + [list/flat-list {:style styles/networks-list + :data (vals networks) + :render-fn (render-network network) + :header [react/view + [actions-view + [common/bottom-shadow] + [common/form-title (i18n/label :t/existing-networks) + {:count-value (count networks)}] + [common/list-header]]] + :footer [react/view + [common/list-footer] + [common/bottom-shadow]]}]]])) diff --git a/src/status_im/ui/screens/wallet/main/views.cljs b/src/status_im/ui/screens/wallet/main/views.cljs index 7c8d4aab9e..7ff90c442e 100644 --- a/src/status_im/ui/screens/wallet/main/views.cljs +++ b/src/status_im/ui/screens/wallet/main/views.cljs @@ -101,7 +101,7 @@ [react/text {:style styles/asset-item-currency :uppercase? true :number-of-lines 1} - symbol]] + (clojure.core/name symbol)]] [list/item-icon {:icon :icons/forward}]]]] [add-asset])) diff --git a/src/status_im/ui/screens/wallet/transactions/views.cljs b/src/status_im/ui/screens/wallet/transactions/views.cljs index 6af8fd079b..f38c59794f 100644 --- a/src/status_im/ui/screens/wallet/transactions/views.cljs +++ b/src/status_im/ui/screens/wallet/transactions/views.cljs @@ -146,17 +146,16 @@ [list/item-primary label] [list/item-secondary symbol]]]) -(defn- item-filter-type [{:keys [id label checked?]}] - (let [kid (keyword id)] - [item-filter {:icon (transaction-type->icon kid) :checked? checked? :path {:type kid}} - [list/item-content - [list/item-primary-only label]]])) +(defn- render-item-filter [{:keys [id label checked?]}] + [item-filter {:icon (transaction-type->icon id) :checked? checked? :path {:type id}} + [list/item-content + [list/item-primary-only label]]]) (defn- wrap-filter-data [m] ;; TODO(jeluard) Restore tokens filtering once token support is added [{:title (i18n/label :t/transactions-filter-type) :key :type - :renderItem (list/wrap-render-fn item-filter-type) + :render-fn render-item-filter ;(list/wrap-render-fn item-filter-type) :data (:type m)}]) (defview filter-history [] diff --git a/src/status_im/utils/listview.cljs b/src/status_im/utils/listview.cljs deleted file mode 100644 index 8a55fd71d0..0000000000 --- a/src/status_im/utils/listview.cljs +++ /dev/null @@ -1,20 +0,0 @@ -(ns status-im.utils.listview) - -(defn clone-with-rows [ds rows] - (.cloneWithRows ds (reduce (fn [ac el] (.push ac el) ac) - (clj->js []) rows))) - -(defn- data-source [config] - (js/ReactNative.ListView.DataSource. (clj->js config))) - -(defn to-datasource [items] - (clone-with-rows (data-source {:rowHasChanged not=}) items)) - -(defn- clone-with-rows-inverted [ds rows] - (let [rows (reduce (fn [ac el] (.push ac el) ac) - (clj->js []) (reverse rows)) - row-ids (.reverse (.map rows (fn [_ index] index)))] - (.cloneWithRows ds rows row-ids))) - -(defn to-datasource-inverted [items] - (clone-with-rows-inverted (data-source {:rowHasChanged not=}) items)) diff --git a/test/cljs/status_im/react_native/js_dependencies.cljs b/test/cljs/status_im/react_native/js_dependencies.cljs index 974d61f13f..6281d4331b 100644 --- a/test/cljs/status_im/react_native/js_dependencies.cljs +++ b/test/cljs/status_im/react_native/js_dependencies.cljs @@ -16,7 +16,6 @@ (def image-crop-picker #js {}) (def image-resizer #js {}) (def instabug #js {}) -(def invertible-scroll-view #js {}) (def linear-gradient #js {}) (def mapbox-gl #js {:setAccessToken (fn [])}) (def nfc #js {})