From d7f3946c06e8cdb19dc41cd10a5ce487db30c585 Mon Sep 17 00:00:00 2001 From: Omar Basem Date: Fri, 17 May 2024 10:44:34 +0400 Subject: [PATCH] feat(wallet): Activity Items - Sections (#19906) feat(wallet): Activity Items - Sections (#19906) --- .../contexts/wallet/account/view.cljs | 3 +- .../wallet/common/activity_tab/view.cljs | 12 ++++--- src/status_im/subs/wallet/activities.cljs | 23 +++++++++---- .../subs/wallet/activities_test.cljs | 33 +++++++++++++++++++ src/status_im/subs/wallet/send.cljs | 7 ++-- src/utils/datetime.cljs | 14 ++++++++ src/utils/datetime_test.cljs | 29 ++++++++++++++++ 7 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 src/status_im/subs/wallet/activities_test.cljs diff --git a/src/status_im/contexts/wallet/account/view.cljs b/src/status_im/contexts/wallet/account/view.cljs index 0c1c232abe..b6ce0bf77d 100644 --- a/src/status_im/contexts/wallet/account/view.cljs +++ b/src/status_im/contexts/wallet/account/view.cljs @@ -63,8 +63,7 @@ :size 32 :default-active @selected-tab :data (tabs-data watch-only?) - :on-change (rn/use-callback (fn [tab] - (reset! selected-tab tab))) + :on-change (rn/use-callback (fn [tab] (reset! selected-tab tab))) :scrollable? true :scroll-on-press? true}] [tabs/view {:selected-tab @selected-tab}] diff --git a/src/status_im/contexts/wallet/common/activity_tab/view.cljs b/src/status_im/contexts/wallet/common/activity_tab/view.cljs index 2a93b18e69..bc43a3808a 100644 --- a/src/status_im/contexts/wallet/common/activity_tab/view.cljs +++ b/src/status_im/contexts/wallet/common/activity_tab/view.cljs @@ -66,8 +66,10 @@ {:title (i18n/label :t/no-activity) :description (i18n/label :t/empty-tab-description) :image (resources/get-themed-image :no-activity theme)}] - [rn/flat-list - {:data activity-list - :style {:flex 1} - :content-container-style {:padding-bottom jump-to.constants/floating-shell-button-height} - :render-fn activity-item}]))) + [rn/section-list + {:sections activity-list + :sticky-section-headers-enabled false + :style {:flex 1} + :content-container-style {:padding-bottom jump-to.constants/floating-shell-button-height} + :render-fn activity-item + :render-section-header-fn (fn [{:keys [title]}] [quo/divider-date title])}]))) diff --git a/src/status_im/subs/wallet/activities.cljs b/src/status_im/subs/wallet/activities.cljs index 38f10ff45b..7973ee0049 100644 --- a/src/status_im/subs/wallet/activities.cljs +++ b/src/status_im/subs/wallet/activities.cljs @@ -1,17 +1,26 @@ (ns status-im.subs.wallet.activities - (:require [re-frame.core :as rf])) + (:require + [re-frame.core :as rf] + [status-im.contexts.wallet.common.activity-tab.constants :as constants] + [utils.datetime :as datetime])) (rf/reg-sub :wallet/all-activities :<- [:wallet] :-> :activities) -(rf/reg-sub - :wallet/activities-for-current-viewing-account +(rf/reg-sub :wallet/activities-for-current-viewing-account :<- [:wallet/all-activities] :<- [:wallet/current-viewing-account-address] (fn [[activities current-viewing-account-address]] - (filter (fn [{:keys [sender recipient]}] - (or (= sender current-viewing-account-address) - (= recipient current-viewing-account-address))) - activities))) + (->> activities + (filter (fn [{:keys [sender recipient activity-type]}] + (let [receiving-activity? (= activity-type constants/wallet-activity-type-receive) + relevant-address (if receiving-activity? recipient sender)] + (= relevant-address current-viewing-account-address)))) + (distinct) + (group-by (fn [{:keys [timestamp]}] + (datetime/timestamp->relative-short-date (* timestamp 1000)))) + (map (fn [[date activities]] + {:title date :data activities :timestamp (:timestamp (first activities))})) + (sort-by (fn [{:keys [timestamp]}] (- timestamp)))))) diff --git a/src/status_im/subs/wallet/activities_test.cljs b/src/status_im/subs/wallet/activities_test.cljs new file mode 100644 index 0000000000..8cef0e7355 --- /dev/null +++ b/src/status_im/subs/wallet/activities_test.cljs @@ -0,0 +1,33 @@ +(ns status-im.subs.wallet.activities-test + (:require + [cljs.test :refer [is testing]] + [re-frame.db :as rf-db] + status-im.subs.root + status-im.subs.wallet.collectibles + [test-helpers.unit :as h] + [utils.re-frame :as rf])) + +(h/deftest-sub :wallet/all-activities + [sub-name] + (testing "Return the activities list from wallet data" + (swap! rf-db/app-db assoc-in + [:wallet :activities] + [{:id 1 :name "Transaction1"} + {:id 2 :name "Transaction2"}]) + (is (= [{:id 1 :name "Transaction1"} {:id 2 :name "Transaction2"}] (rf/sub [sub-name]))))) + +(h/deftest-sub :wallet/activities-for-current-viewing-account + [sub-name] + (testing "Return activities filtered and grouped by account and dates" + (swap! rf-db/app-db + (fn [db] + (-> db + (assoc-in [:wallet :activities] + [{:sender "acc1" :recipient "acc2" :timestamp 1588291200} + {:sender "acc2" :recipient "acc1" :timestamp 1588377600} + {:sender "acc3" :recipient "acc4" :timestamp 1588464000}]) + (assoc-in [:wallet :current-viewing-account-address] "acc1")))) + (is (= [{:title "May 1, 2020" + :data [{:sender "acc1" :recipient "acc2" :timestamp 1588291200}] + :timestamp 1588291200}] + (rf/sub [sub-name]))))) diff --git a/src/status_im/subs/wallet/send.cljs b/src/status_im/subs/wallet/send.cljs index 465d096f7b..ac6609cd2d 100644 --- a/src/status_im/subs/wallet/send.cljs +++ b/src/status_im/subs/wallet/send.cljs @@ -37,10 +37,11 @@ :wallet/recent-recipients :<- [:wallet/activities-for-current-viewing-account] :<- [:wallet/current-viewing-account-address] - (fn [[activities current-viewing-account-address]] - (let [users-sent-transactions (filter (fn [{:keys [sender]}] + (fn [[sections current-viewing-account-address]] + (let [all-transactions (mapcat :data sections) + users-sent-transactions (filter (fn [{:keys [sender]}] (= sender current-viewing-account-address)) - activities)] + all-transactions)] (set (map :recipient users-sent-transactions))))) (rf/reg-sub diff --git a/src/utils/datetime.cljs b/src/utils/datetime.cljs index 7d0a8bf9c9..d666578947 100644 --- a/src/utils/datetime.cljs +++ b/src/utils/datetime.cljs @@ -209,6 +209,20 @@ (previous-years? datetime) (.format ^js (date-fmt) datetime)))) +(defn full-date->short-date + [s] + (let [words (string/split s #"\s+") + last-word (last words)] + (if (or (= "AM" last-word) (= "PM" last-word)) + (string/join " " (take (- (count words) 2) words)) + s))) + +(defn timestamp->relative-short-date + [ms] + (->> ms + timestamp->relative + full-date->short-date)) + (defn timestamp->mini-date [ms] (.format ^js (short-date-fmt) diff --git a/src/utils/datetime_test.cljs b/src/utils/datetime_test.cljs index bdcd7e2811..07f0b99bd5 100644 --- a/src/utils/datetime_test.cljs +++ b/src/utils/datetime_test.cljs @@ -174,6 +174,35 @@ (is (= "Today 12:00 PM" (datetime/timestamp->relative 163684800000))) (is (= "Today 12:00 AM" (datetime/timestamp->relative 163641600000)))))) +(deftest timestamp->relative-short-date-test + (with-redefs [t/*ms-fn* (constantly 163696545000) + datetime/time-zone-offset (t/period :hours 0) + datetime/is-24-hour (constantly false)] + (testing "short date format for previous years" + (is (= "Dec 31, 1974" (datetime/timestamp->relative-short-date 157766399000))) + (is (= "Jan 1, 1973" (datetime/timestamp->relative-short-date 94694400000)))) + + (testing "short date format for dates 7 days ago or older, but in the current year" + (is (= "03 Mar" (datetime/timestamp->relative-short-date 163091745000))) + (is (= "02 Mar" (datetime/timestamp->relative-short-date 163004400000))) + (is (= "01 Jan" (datetime/timestamp->relative-short-date 157820400000)))) + + (testing "short date format for dates within the last 6 days" + (is (= "Sat" (datetime/timestamp->relative-short-date 163523745000))) + (is (= "Fri" (datetime/timestamp->relative-short-date 163437345000))) + (is (= "Thu" (datetime/timestamp->relative-short-date 163350945000))) + (is (= "Wed" (datetime/timestamp->relative-short-date 163264545000))) + (is (= "Tue" (datetime/timestamp->relative-short-date 163178145000)))) + + (testing "short date format for yesterday" + (is (= "Yesterday" (datetime/timestamp->relative-short-date 163610145000))) + (is (= "Yesterday" (datetime/timestamp->relative-short-date 163641599000)))) + + (testing "short date format for today, at various timestamps" + (is (= "Today" (datetime/timestamp->relative-short-date 163696545000))) + (is (= "Today" (datetime/timestamp->relative-short-date 163684800000))) + (is (= "Today" (datetime/timestamp->relative-short-date 163641600000)))))) + #_((deftest day-relative-before-yesterday-force-24H-test (with-redefs [t/*ms-fn* (constantly epoch-plus-3d) datetime/is-24-hour (constantly true)