diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 67a60b79df..beb67f788f 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -1241,13 +1241,6 @@ #(when ens-name (contact/name-verified % public-key ens-name)))))) -;; search module - -(handlers/register-handler-fx - :search/filter-changed - (fn [cofx [_ search-filter]] - (search/filter-changed cofx search-filter))) - ;; pairing module (handlers/register-handler-fx diff --git a/src/status_im/search/core.cljs b/src/status_im/search/core.cljs index a10e88873e..2f773921f0 100644 --- a/src/status_im/search/core.cljs +++ b/src/status_im/search/core.cljs @@ -1,5 +1,17 @@ (ns status-im.search.core (:require [status-im.utils.fx :as fx])) -(fx/defn filter-changed [cofx search-filter] - {:db (assoc-in (:db cofx) [:ui/search :filter] search-filter)}) +(fx/defn home-filter-changed + {:events [:search/home-filter-changed]} + [cofx search-filter] + {:db (assoc-in (:db cofx) [:ui/search :home-filter] search-filter)}) + +(fx/defn currency-filter-changed + {:events [:search/currency-filter-changed]} + [cofx search-filter] + {:db (assoc-in (:db cofx) [:ui/search :currency-filter] search-filter)}) + +(fx/defn token-filter-changed + {:events [:search/token-filter-changed]} + [cofx search-filter] + {:db (assoc-in (:db cofx) [:ui/search :token-filter] search-filter)}) \ No newline at end of file diff --git a/src/status_im/subs.cljs b/src/status_im/subs.cljs index 7734cb04fb..ff80bcba33 100644 --- a/src/status_im/subs.cljs +++ b/src/status_im/subs.cljs @@ -375,10 +375,22 @@ (get-in animations [type item-id :delete-swiped]))) (re-frame/reg-sub - :search/filter + :search/home-filter :<- [:ui/search] (fn [search] - (get search :filter))) + (get search :home-filter))) + +(re-frame/reg-sub + :search/currency-filter + :<- [:ui/search] + (fn [search] + (get search :currency-filter))) + +(re-frame/reg-sub + :search/token-filter + :<- [:ui/search] + (fn [search] + (get search :token-filter))) (defn- node-version [web3-node-version] (or web3-node-version "N/A")) @@ -1011,7 +1023,7 @@ (re-frame/reg-sub :home-items :<- [:chats/active-chats] - :<- [:search/filter] + :<- [:search/home-filter] :<- [:search/filtered-chats] (fn [[chats search-filter filtered-chats]] (if (or (nil? search-filter) @@ -1828,25 +1840,53 @@ the search-filter apply-filter returns nil if there is no element that match the filter apply-filter returns full collection if the search-filter is empty" - [search-filter coll extract-attributes-fn] - (if (not-empty search-filter) - (let [search-filter (string/lower-case search-filter) - results (filter (fn [element] - (some (fn [s] - (when (string? s) - (string/includes? (string/lower-case s) - search-filter))) - (extract-attributes-fn element))) - coll)] - (sort-by-timestamp results)) - (sort-by-timestamp coll))) + [search-filter coll extract-attributes-fn sort?] + (let [results (if (not-empty search-filter) + (let [search-filter (string/lower-case search-filter)] + (filter (fn [element] + (some (fn [v] + (let [s (cond (string? v) v + (keyword? v) (name v))] + (when (string? s) + (string/includes? (string/lower-case s) + search-filter)))) + (extract-attributes-fn element))) + coll)) + coll)] + (if sort? + (sort-by-timestamp results) + results))) (re-frame/reg-sub :search/filtered-chats :<- [:chats/active-chats] - :<- [:search/filter] + :<- [:search/home-filter] (fn [[chats search-filter]] - (apply-filter search-filter chats extract-chat-attributes))) + (apply-filter search-filter chats extract-chat-attributes true))) + +(defn extract-currency-attributes [currency] + (let [{:keys [code display-name]} (val currency)] + [code display-name])) + +(re-frame/reg-sub + :search/filtered-currencies + :<- [:search/currency-filter] + (fn [search-currency-filter] + {:search-filter search-currency-filter + :currencies (apply-filter search-currency-filter constants/currencies extract-currency-attributes false)})) + +(defn extract-token-attributes [token] + (let [{:keys [symbol name]} token] + [symbol name])) + +(re-frame/reg-sub + :wallet/filtered-grouped-chain-tokens + :<- [:wallet/grouped-chain-tokens] + :<- [:search/token-filter] + (fn [[{custom-tokens true default-tokens nil} search-token-filter]] + {:search-filter search-token-filter + :tokens {true (apply-filter search-token-filter custom-tokens extract-token-attributes false) + nil (apply-filter search-token-filter default-tokens extract-token-attributes false)}})) ;; TRIBUTE TO TALK (re-frame/reg-sub diff --git a/src/status_im/ui/components/search_input/styles.cljs b/src/status_im/ui/components/search_input/styles.cljs new file mode 100644 index 0000000000..e9712af579 --- /dev/null +++ b/src/status_im/ui/components/search_input/styles.cljs @@ -0,0 +1,27 @@ +(ns status-im.ui.components.search-input.styles + (:require [status-im.ui.components.colors :as colors] + [status-im.utils.styles :as styles])) + +(styles/def search-input + {:flex 1 + :android {:margin 0 + :padding 0}}) + +(def search-input-height 56) + +(def search-container + {:height search-input-height + :flex-direction :row + :padding-horizontal 16 + :background-color colors/white + :align-items :center + :justify-content :center}) + +(def search-input-container + {:background-color colors/gray-lighter + :flex 1 + :flex-direction :row + :height 36 + :align-items :center + :justify-content :center + :border-radius 8}) \ No newline at end of file diff --git a/src/status_im/ui/components/search_input/view.cljs b/src/status_im/ui/components/search_input/view.cljs new file mode 100644 index 0000000000..182d58f83a --- /dev/null +++ b/src/status_im/ui/components/search_input/view.cljs @@ -0,0 +1,52 @@ +(ns status-im.ui.components.search-input.view + (:require-macros [status-im.utils.views :as views]) + (:require [reagent.core :as reagent] + [status-im.i18n :as i18n] + [status-im.ui.components.react :as react] + [status-im.ui.components.colors :as colors] + [status-im.ui.components.search-input.styles :as styles] + [status-im.ui.components.icons.vector-icons :as icons])) + +(views/defview search-input [{:keys [on-cancel + on-focus + on-change + search-active? + search-container-style + search-filter + auto-focus]}] + (views/letsubs + [input-ref (reagent/atom nil)] + [react/view {:style (or search-container-style styles/search-container)} + [react/view {:style styles/search-input-container} + [icons/icon :main-icons/search {:color colors/gray + :container-style {:margin-left 6 + :margin-right 2}}] + [react/text-input {:placeholder (i18n/label :t/search) + :blur-on-submit true + :multiline false + :ref #(reset! input-ref %) + :style styles/search-input + :default-value search-filter + :auto-focus auto-focus + :auto-correct false + :auto-capitalize false + :on-focus #(do + (when on-focus + (on-focus search-filter)) + (reset! search-active? true)) + :on-change (fn [e] + (let [native-event (.-nativeEvent e) + text (.-text native-event)] + (when on-change + (on-change text))))}]] + (when @search-active? + [react/touchable-highlight + {:on-press (fn [] + (.clear @input-ref) + (.blur @input-ref) + (when on-cancel + (on-cancel)) + (reset! search-active? false)) + :style {:margin-left 16}} + [react/text {:style {:color colors/blue}} + (i18n/label :t/cancel)]])])) \ No newline at end of file diff --git a/src/status_im/ui/screens/currency_settings/views.cljs b/src/status_im/ui/screens/currency_settings/views.cljs index e628e53bd2..13cd4f431c 100644 --- a/src/status_im/ui/screens/currency_settings/views.cljs +++ b/src/status_im/ui/screens/currency_settings/views.cljs @@ -1,18 +1,19 @@ (ns status-im.ui.screens.currency-settings.views (:require-macros [status-im.utils.views :as views]) (:require [re-frame.core :as re-frame] - [status-im.i18n :as i18n] + [reagent.core :as reagent] [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.toolbar.view :as toolbar] [status-im.ui.screens.profile.components.views :as profile.components] [status-im.ui.screens.currency-settings.styles :as styles] - [status-im.constants :as constants] - [status-im.ui.components.topbar :as topbar])) + [status-im.ui.components.topbar :as topbar] + [status-im.ui.components.search-input.view :as search-input])) + +(defonce search-active? (reagent/atom false)) (defn render-currency [current-currency-id] - (fn [{:keys [id code display-name] :as currency}] + (fn [{:keys [id code display-name]}] (let [selected? (= id current-currency-id)] [react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet.settings.ui/currency-selected id]) @@ -24,13 +25,27 @@ [vector-icons/icon :main-icons/check {:color :active}])]]))) (views/defview currency-settings [] - (views/letsubs [currency-id [:wallet.settings/currency]] + (views/letsubs [currency-id [:wallet.settings/currency] + {:keys [currencies search-filter]} [:search/filtered-currencies]] + {:component-will-unmount #(do + (re-frame/dispatch [:search/currency-filter-changed nil]) + (reset! search-active? false))} [react/view {:flex 1} [topbar/topbar {:title :t/main-currency}] [react/view styles/wrapper - [list/flat-list {:data (->> constants/currencies + [search-input/search-input + {:search-active? search-active? + :search-filter search-filter + :on-cancel #(re-frame/dispatch [:search/currency-filter-changed nil]) + :on-focus (fn [search-filter] + (when-not search-filter + (re-frame/dispatch [:search/currency-filter-changed ""]))) + :on-change (fn [text] + (re-frame/dispatch [:search/currency-filter-changed text]))}] + [list/flat-list {:data (->> currencies vals (sort #(compare (:code %1) (:code %2)))) :key-fn :code :separator (profile.components/settings-item-separator) - :render-fn (render-currency currency-id)}]]])) + :render-fn (render-currency currency-id) + :keyboardShouldPersistTaps :always}]]])) \ No newline at end of file diff --git a/src/status_im/ui/screens/home/styles.cljs b/src/status_im/ui/screens/home/styles.cljs index b07580520d..04f3e0b640 100644 --- a/src/status_im/ui/screens/home/styles.cljs +++ b/src/status_im/ui/screens/home/styles.cljs @@ -1,6 +1,7 @@ (ns status-im.ui.screens.home.styles (:require [status-im.ui.components.colors :as colors] [status-im.utils.styles :as styles] + [status-im.ui.components.search-input.styles :as search-input.styles] [status-im.utils.platform :as platform])) (defn toolbar [] @@ -22,35 +23,14 @@ :color colors/gray :desktop {:max-height 20}}) -(def search-input-height 56) - (def search-container (merge - {:height search-input-height - :flex-direction :row - :padding-horizontal 16 - :background-color colors/white - :align-items :center - :justify-content :center} + search-input.styles/search-container (when platform/ios? {:position :absolute - :top (- search-input-height) + :top (- search-input.styles/search-input-height) :width "100%"}))) -(def search-input-container - {:background-color colors/gray-lighter - :flex 1 - :flex-direction :row - :height 36 - :align-items :center - :justify-content :center - :border-radius 8}) - -(styles/def search-input - {:flex 1 - :android {:margin 0 - :padding 0}}) - (def filter-section-title {:margin-left 16 :margin-top 14 diff --git a/src/status_im/ui/screens/home/views.cljs b/src/status_im/ui/screens/home/views.cljs index 6620e4aafe..dd72b90ae3 100644 --- a/src/status_im/ui/screens/home/views.cljs +++ b/src/status_im/ui/screens/home/views.cljs @@ -18,7 +18,9 @@ [status-im.constants :as constants] [status-im.ui.components.colors :as colors] [status-im.ui.screens.add-new.new-public-chat.view :as new-public-chat] - [status-im.ui.components.button :as button]) + [status-im.ui.components.button :as button] + [status-im.ui.components.search-input.view :as search-input] + [status-im.ui.components.search-input.styles :as search-input.styles]) (:require-macros [status-im.utils.views :as views])) (defonce search-active? (reagent/atom false)) @@ -91,50 +93,17 @@ [home-tooltip-view]) [react/view {:height 68 :flex 1}]])) -(views/defview search-input [{:keys [on-cancel on-focus on-change]}] - (views/letsubs - [{:keys [search-filter]} [:home-items] - input-ref (reagent/atom nil)] - [react/view {:style styles/search-container} - [react/view {:style styles/search-input-container} - [icons/icon :main-icons/search {:color colors/gray - :container-style {:margin-left 6 - :margin-right 2}}] - [react/text-input {:placeholder (i18n/label :t/search) - :blur-on-submit true - :multiline false - :ref #(reset! input-ref %) - :style styles/search-input - :default-value search-filter - :on-focus #(do - (when on-focus - (on-focus search-filter)) - (reset! search-active? true)) - :on-change (fn [e] - (let [native-event (.-nativeEvent e) - text (.-text native-event)] - (when on-change - (on-change text))))}]] - (when @search-active? - [react/touchable-highlight - {:on-press (fn [] - (.clear @input-ref) - (.blur @input-ref) - (when on-cancel - (on-cancel)) - (reset! search-active? false)) - :style {:margin-left 16}} - [react/text {:style {:color colors/blue}} - (i18n/label :t/cancel)]])])) - -(defn search-input-wrapper [] - [search-input - {:on-cancel #(re-frame/dispatch [:search/filter-changed nil]) +(defn search-input-wrapper [search-filter] + [search-input/search-input + {:search-active? search-active? + :search-container-style styles/search-container + :search-filter search-filter + :on-cancel #(re-frame/dispatch [:search/home-filter-changed nil]) :on-focus (fn [search-filter] (when-not search-filter - (re-frame/dispatch [:search/filter-changed ""]))) + (re-frame/dispatch [:search/home-filter-changed ""]))) :on-change (fn [text] - (re-frame/dispatch [:search/filter-changed text]))}]) + (re-frame/dispatch [:search/home-filter-changed text]))}]) (defn section-footer [{:keys [title data]}] (when (and @search-active? (empty? data)) @@ -151,7 +120,7 @@ (views/defview home-filtered-items-list [] (views/letsubs - [{:keys [chats all-home-items]} [:home-items] + [{:keys [chats all-home-items search-filter]} [:home-items] {:keys [hide-home-tooltip?]} [:multiaccount]] (let [list-ref (reagent/atom nil)] [list/section-list @@ -164,19 +133,19 @@ :keyboard-should-persist-taps :always :ref #(reset! list-ref %) :footer [chat-list-footer hide-home-tooltip?] - :contentInset {:top styles/search-input-height} + :contentInset {:top search-input.styles/search-input-height} :render-section-header-fn (fn [data] [react/view]) :render-section-footer-fn section-footer :render-fn (fn [home-item] [inner-item/home-list-item home-item]) :header (when (or @search-active? (not-empty all-home-items)) - [search-input-wrapper]) + [search-input-wrapper search-filter]) :on-scroll-end-drag (fn [e] (let [y (-> e .-nativeEvent .-contentOffset .-y) hide-searchbar? (cond - platform/ios? (and (neg? y) (> y (- (/ styles/search-input-height 2)))) - platform/android? (and (< y styles/search-input-height) (> y (/ styles/search-input-height 2))))] + platform/ios? (and (neg? y) (> y (- (/ search-input.styles/search-input-height 2)))) + platform/android? (and (< y search-input.styles/search-input-height) (> y (/ search-input.styles/search-input-height 2))))] (if hide-searchbar? (.scrollToLocation @list-ref #js {:sectionIndex 0 :itemIndex 0}))))})]))) diff --git a/src/status_im/ui/screens/wallet/settings/views.cljs b/src/status_im/ui/screens/wallet/settings/views.cljs index 0ee4bd1425..ea9694f8b6 100644 --- a/src/status_im/ui/screens/wallet/settings/views.cljs +++ b/src/status_im/ui/screens/wallet/settings/views.cljs @@ -7,9 +7,12 @@ [status-im.ui.components.styles :as components.styles] [status-im.ui.components.list-item.views :as list-item] [reagent.core :as reagent] - [status-im.ui.components.topbar :as topbar]) + [status-im.ui.components.topbar :as topbar] + [status-im.ui.components.search-input.view :as search-input]) (:require-macros [status-im.utils.views :refer [defview letsubs]])) +(defonce search-active? (reagent/atom false)) + (defn toolbar [] [topbar/topbar {:title :t/wallet-assets @@ -70,10 +73,23 @@ [render-token token]) (defview manage-assets [] - (letsubs [{custom-tokens true default-tokens nil} [:wallet/grouped-chain-tokens]] + (letsubs [{search-filter :search-filter + {custom-tokens true default-tokens nil} :tokens} [:wallet/filtered-grouped-chain-tokens]] + {:component-will-unmount #(do + (re-frame/dispatch [:search/token-filter-changed nil]) + (reset! search-active? false))} [react/view (merge components.styles/flex {:background-color :white}) [toolbar] [react/view {:style components.styles/flex} + [search-input/search-input + {:search-active? search-active? + :search-filter search-filter + :on-cancel #(re-frame/dispatch [:search/token-filter-changed nil]) + :on-focus (fn [search-filter] + (when-not search-filter + (re-frame/dispatch [:search/token-filter-changed ""]))) + :on-change (fn [text] + (re-frame/dispatch [:search/token-filter-changed text]))}] [list/section-list {:header [react/view {:margin-top 16}