Skip to content

Commit f9dc282

Browse files
vkjrflexsurfer
andauthored
Feature/news feed copy (#22626)
* [#22404] [News Feed] Implement News AC component * QA * Incoming rss feed sanitized from html tags. * test fix * test * use fast-image instead of rn image to avoid problem on android * uncomment marking as read --------- Co-authored-by: andrey <[email protected]>
1 parent 4f84b0a commit f9dc282

File tree

11 files changed

+165
-10
lines changed

11 files changed

+165
-10
lines changed

src/legacy/status_im/data_store/activities.cljs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
(ns legacy.status-im.data-store.activities
22
(:require
33
[clojure.set :as set]
4+
[clojure.string :as string]
45
[legacy.status-im.data-store.messages :as messages]
56
[status-im.constants :as constants]
67
[status-im.contexts.shell.activity-center.notification-types :as notification-types]))
@@ -53,6 +54,23 @@
5354

5455
chat))
5556

57+
(defn strip-html
58+
[html]
59+
(-> html
60+
;; Replace block-level tags with newlines
61+
(clojure.string/replace #"</?(h[1-6]|p|div|br|li|ul|ol|section|article|blockquote)[^>]*>" "\n")
62+
;; Remove all remaining tags
63+
(clojure.string/replace #"<[^>]+>" "")
64+
;; Decode common HTML entities
65+
(clojure.string/replace #"&nbsp;" " ")
66+
(clojure.string/replace #"&amp;" "&")
67+
;; Collapse multiple newlines into one
68+
(clojure.string/replace #"\n+" "\n")
69+
;; Trim spaces at start/end of lines
70+
(clojure.string/replace #"[ \t]+\n" "\n")
71+
(clojure.string/replace #"\n[ \t]+" "\n")
72+
clojure.string/trim))
73+
5674
(defn <-rpc
5775
[item]
5876
(-> item
@@ -64,10 +82,19 @@
6482
:communityId :community-id
6583
:installationId :installation-id
6684
:membershipStatus :membership-status
67-
:albumMessages :album-messages})
85+
:albumMessages :album-messages
86+
:newsImageUrl :news-image-url
87+
:newsTitle :news-title
88+
:newsDescription :news-description
89+
:newsContent :news-content
90+
:newsLink :news-link
91+
:newsLinkLabel :news-link-label})
6892
(update :last-message #(when % (messages/<-rpc %)))
6993
(update :message #(when % (messages/<-rpc %)))
7094
(update :reply-message #(when % (messages/<-rpc %)))
95+
(update :news-description #(when % (strip-html %)))
96+
(update :news-title #(when % (strip-html %)))
97+
(update :news-content #(when % (strip-html %)))
7198
(dissoc :chatId)))
7299

73100
(defn <-rpc-seen-state

src/legacy/status_im/data_store/activities_test.cljs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020

2121
(deftest <-rpc-test
2222
(testing "renames keys"
23-
(is (= {:name chat-name
24-
:chat-id chat-id
25-
:contact-verification-status constants/contact-verification-status-pending}
26-
(-> raw-notification
27-
store/<-rpc
28-
(dissoc :last-message :message :reply-message)))))
23+
(is
24+
(= {:name chat-name
25+
:chat-id chat-id
26+
:contact-verification-status constants/contact-verification-status-pending}
27+
(->
28+
raw-notification
29+
store/<-rpc
30+
(dissoc :last-message :message :reply-message :news-title :news-content :news-description)))))
2931

3032
(testing "transforms messages from RPC response"
3133
(is

src/status_im/contexts/settings/privacy_and_security/view.cljs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
(let [customization-color (rf/sub [:profile/customization-color])
4343
privacy-mode-enabled? (rf/sub [:privacy-mode/privacy-mode-enabled?])
4444
preview-privacy? (rf/sub [:profile/preview-privacy?])
45+
news-feed-enabled? (rf/sub [:profile/news-feed-enabled?])
4546
see-profile-pictures-from (rf/sub [:profile/pictures-visibility])
4647
show-profile-pictures-to (rf/sub [:multiaccount/profile-pictures-show-to])
4748

@@ -51,6 +52,14 @@
5152
(not preview-privacy?)]))
5253
[preview-privacy?])
5354

55+
toggle-news-feed
56+
(rn/use-callback (fn []
57+
(rf/dispatch [:profile.settings/profile-update :news-feed-enabled?
58+
(not news-feed-enabled?)])
59+
(rf/dispatch [:profile.settings/profile-update :news-rss-enabled?
60+
(not news-feed-enabled?)]))
61+
[news-feed-enabled?])
62+
5463
open-see-profile-pictures-from-options
5564
(rn/use-callback (fn []
5665
(rf/dispatch
@@ -104,6 +113,15 @@
104113
:blur? true
105114
:action :arrow
106115
:action-props {:on-change #(rf/dispatch [:open-modal
107-
:screen/settings.share-usage-data])}}]
116+
:screen/settings.share-usage-data])}}
117+
{:title (i18n/label :t/status-news-rss)
118+
:description :text
119+
:description-props {:text (i18n/label :t/rss-privacy-warning)}
120+
:blur? true
121+
:action :selector
122+
:action-props {:on-change toggle-news-feed
123+
:checked? news-feed-enabled?
124+
:id :news-feed
125+
:customization-color customization-color}}]
108126
:blur? true
109127
:list-type :settings}]]))
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
(ns status-im.contexts.shell.activity-center.notification.news.view
2+
(:require [clojure.string :as string]
3+
[promesa.core :as promesa]
4+
[quo.core :as quo]
5+
[react-native.core :as rn]
6+
[react-native.fast-image :as fast-image]
7+
[react-native.gesture :as gesture]
8+
[status-im.contexts.shell.activity-center.notification.common.view :as common]
9+
[utils.datetime :as datetime]
10+
[utils.i18n :as i18n]
11+
[utils.re-frame :as rf]))
12+
13+
(defn auto-resized-image
14+
[url]
15+
(let [[height set-height] (rn/use-state nil)
16+
window-width (- (:width (rn/get-window)) 40)]
17+
(rn/use-effect #(-> (rn/image-get-size url)
18+
(promesa/then (fn [[w h]]
19+
(let [scale (/ window-width w)
20+
new-height (* h scale)]
21+
(set-height new-height))))))
22+
(if height
23+
[fast-image/fast-image
24+
{:source url
25+
:style {:width window-width
26+
:height height
27+
:align-self :center
28+
:border-radius 12}}]
29+
[rn/view {:style {:height 200 :align-items :center :justify-content :center}}
30+
[rn/activity-indicator]])))
31+
32+
(defn news-sheet
33+
[{:keys [news-image-url news-title news-content news-link news-link-label]} timestamp]
34+
(let [customization-color (rf/sub [:profile/customization-color])]
35+
[:<>
36+
[quo/drawer-top {:title news-title :description timestamp}]
37+
[rn/scroll-view {:style {:flex 1}}
38+
(when (not (string/blank? news-image-url))
39+
[auto-resized-image news-image-url])
40+
[quo/text
41+
{:style {:padding-horizontal 20
42+
:padding-vertical 8}}
43+
news-content]]
44+
(when (and (not (string/blank? news-link)) (not (string/blank? news-link-label)))
45+
[quo/bottom-actions
46+
{:button-one-label news-link-label
47+
:button-one-props {:customization-color customization-color
48+
:icon-right :i/external
49+
:on-press (fn []
50+
(rf/dispatch [:browser.ui/open-url news-link])
51+
(rf/dispatch [:hide-bottom-sheet]))}}])]))
52+
53+
(defn view
54+
[{:keys [notification extra-fn]}]
55+
(let [customization-color (rf/sub [:profile/customization-color])
56+
{:keys [news-title
57+
news-description
58+
timestamp
59+
read
60+
id]} notification
61+
timestamp (datetime/timestamp->relative timestamp)
62+
show-bottom-preview (rn/use-callback
63+
(fn []
64+
(rf/dispatch [:activity-center.notifications/mark-as-read id])
65+
(rf/dispatch [:show-bottom-sheet
66+
{:theme :dark
67+
:content (fn []
68+
[news-sheet notification timestamp])}])))]
69+
[common/swipeable
70+
{:left-button common/swipe-button-read-or-unread
71+
:left-on-press common/swipe-on-press-toggle-read
72+
:right-button common/swipe-button-delete
73+
:right-on-press common/swipe-on-press-delete
74+
:extra-fn extra-fn}
75+
[gesture/touchable-without-feedback
76+
{:on-press show-bottom-preview}
77+
[quo/activity-log
78+
{:title news-title
79+
:customization-color customization-color
80+
:icon :i/status-logo-bw
81+
:timestamp timestamp
82+
:unread? (not read)
83+
:context [[quo/text {} news-description]]
84+
:items [{:type :button
85+
:subtype :primary
86+
:key :button-reply
87+
:customization-color customization-color
88+
:label (i18n/label :t/read-more)
89+
:accessibility-label :read-more
90+
:on-press show-bottom-preview}]}]]]))

src/status_im/contexts/shell/activity_center/notification_types.cljs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
(def ^:const contact-verification 10)
1313
(def ^:const new-installation-received 23)
1414
(def ^:const new-installation-created 24)
15+
(def ^:const news-feed 29)
1516

1617
(def ^:const all-supported
1718
#{one-to-one-chat
@@ -24,7 +25,8 @@
2425
community-kicked
2526
contact-verification
2627
new-installation-received
27-
new-installation-created})
28+
new-installation-created
29+
news-feed})
2830

2931
;; TODO: Replace with correct enum values once status-go implements them.
3032
(def ^:const tx 66612)

src/status_im/contexts/shell/activity_center/tabs/view.cljs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
:default-active filter-type
3030
:data [{:id types/no-type
3131
:label (i18n/label :t/all)}
32+
{:id types/news-feed
33+
:label (i18n/label :t/news)
34+
:accessibility-label :tab-news
35+
:notification-dot? (when-not is-mark-all-as-read-undoable?
36+
(contains? types-with-unread types/news-feed))}
3237
{:id types/admin
3338
:label (i18n/label :t/admin)
3439
:accessibility-label :tab-admin

src/status_im/contexts/shell/activity_center/view.cljs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
contact-verification]
1919
[status-im.contexts.shell.activity-center.notification.membership.view :as membership]
2020
[status-im.contexts.shell.activity-center.notification.mentions.view :as mentions]
21+
[status-im.contexts.shell.activity-center.notification.news.view :as news]
2122
[status-im.contexts.shell.activity-center.notification.reply.view :as reply]
2223
[status-im.contexts.shell.activity-center.notification.syncing.view :as syncing]
2324
[status-im.contexts.shell.activity-center.style :as style]
@@ -55,6 +56,9 @@
5556
(= notification-type types/new-installation-created)
5657
[syncing/installation-created-view props]
5758

59+
(= notification-type types/news-feed)
60+
[news/view props]
61+
5862
(types/membership notification-type)
5963
(condp = notification-type
6064
types/private-group-chat [membership/view props]
@@ -69,7 +73,6 @@
6973
(defn view
7074
[]
7175
(let [notifications (rf/sub [:activity-center/notifications])
72-
7376
;; We globally control the active swipeable for all notifications
7477
;; because when a swipe left/right gesture initiates, the previously
7578
;; active swiped notification (if any) must be removed & closed with

src/status_im/subs/profile.cljs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@
234234
(fn [{:keys [preview-privacy?]}]
235235
(boolean preview-privacy?)))
236236

237+
(re-frame/reg-sub :profile/news-feed-enabled?
238+
:<- [:profile/profile]
239+
(fn [{:keys [news-feed-enabled?]}]
240+
(boolean news-feed-enabled?)))
241+
237242
(defn- replace-multiaccount-image-uri
238243
[profile port font-file avatar-opts theme]
239244
(let [{:keys [key-uid images

0 commit comments

Comments
 (0)