feat: spectate community before join (#18070)

This commit is contained in:
yqrashawn 2023-12-22 10:21:10 +08:00 committed by GitHub
parent 5fa9c0cab6
commit a4dc268bc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 304 additions and 74 deletions

View File

@ -86,7 +86,7 @@
(native-module/deserialize-and-compress-key (native-module/deserialize-and-compress-key
community-id community-id
(fn [deserialized-key] (fn [deserialized-key]
(rf/dispatch [:chat.ui/resolve-community-info (str deserialized-key)]) (rf/dispatch [:chat.ui/fetch-community (str deserialized-key)])
(rf/dispatch [:handle-navigation-to-desktop-community-from-mobile (str deserialized-key)])))) (rf/dispatch [:handle-navigation-to-desktop-community-from-mobile (str deserialized-key)]))))
(rf/defn handle-community-chat (rf/defn handle-community-chat

View File

@ -1,7 +1,8 @@
(ns status-im.contexts.chat.messages.link-preview.events (ns status-im.contexts.chat.messages.link-preview.events
(:require (:require
[camel-snake-kebab.core :as csk] [camel-snake-kebab.core :as csk]
[status-im.contexts.communities.events :as communities] [legacy.status-im.mailserver.core :as mailserver]
[schema.core :as schema]
[status-im.contexts.profile.settings.events :as profile.settings.events] [status-im.contexts.profile.settings.events :as profile.settings.events]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[utils.collection] [utils.collection]
@ -41,32 +42,93 @@
(boolean enabled?) (boolean enabled?)
{})) {}))
(rf/defn handle-community-resolved (defn community-resolved
{:events [:chat.ui/community-resolved]} [{:keys [db]} [community-id community]]
[{:keys [db] :as cofx} community-id community] (when community
(rf/merge cofx {:db (update db :communities/resolve-community-info dissoc community-id)
(cond-> {:db (update db :communities/resolve-community-info dissoc community-id)} :fx [[:dispatch [:communities/handle-community community]]
[:dispatch
[:chat.ui/cache-link-preview-data (community-link community-id) community]]]}))
(some? community) (rf/reg-event-fx :chat.ui/community-resolved community-resolved)
(assoc :dispatch
[:chat.ui/cache-link-preview-data (community-link community-id) community]))
(communities/handle-community community)))
(rf/defn handle-community-failed-to-resolve (defn community-failed-to-resolve
{:events [:chat.ui/community-failed-to-resolve]} [{:keys [db]} [community-id]]
[{:keys [db]} community-id]
{:db (update db :communities/resolve-community-info dissoc community-id)}) {:db (update db :communities/resolve-community-info dissoc community-id)})
(rf/defn resolve-community-info (rf/reg-event-fx :chat.ui/community-failed-to-resolve community-failed-to-resolve)
{:events [:chat.ui/resolve-community-info]}
[{:keys [db]} community-id] (defn fetch-community
[{:keys [db]} [community-id]]
(when community-id
{:db (assoc-in db [:communities/resolve-community-info community-id] true) {:db (assoc-in db [:communities/resolve-community-info community-id] true)
:json-rpc/call [{:method "wakuext_requestCommunityInfoFromMailserver" :json-rpc/call [{:method "wakuext_fetchCommunity"
:params [community-id] :params [{:CommunityKey community-id
:on-success #(rf/dispatch [:chat.ui/community-resolved community-id %]) :TryDatabase true
:on-error #(do :WaitForResponse true}]
:on-success (fn [community]
(rf/dispatch [:chat.ui/community-resolved community-id community]))
:on-error (fn [err]
(rf/dispatch [:chat.ui/community-failed-to-resolve community-id]) (rf/dispatch [:chat.ui/community-failed-to-resolve community-id])
(log/error "Failed to request community info from mailserver"))}]}) (log/error {:message
"Failed to request community info from mailserver"
:error err}))}]}))
(schema/=> fetch-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-id [:? :string]]]]]]
[:map
[:db map?]
[:json-rpc/call :schema.common/rpc-call]]])
(rf/reg-event-fx :chat.ui/fetch-community fetch-community)
(defn spectate-community-success
[{:keys [db]} [{:keys [communities]}]]
(when-let [community (first communities)]
{:db (-> db
(assoc-in [:communities (:id community) :spectated] true)
(assoc-in [:communities (:id community) :spectating] false))
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch [::mailserver/request-messages]]]}))
(rf/reg-event-fx :chat.ui/spectate-community-success spectate-community-success)
(defn spectate-community-failed
[{:keys [db]} [community-id]]
{:db (assoc-in db [:communities community-id :spectating] false)})
(rf/reg-event-fx :chat.ui/spectate-community-failed spectate-community-failed)
(defn spectate-community
[{:keys [db]} [community-id]]
(let [{:keys [spectated spectating joined]} (get-in db [:communities community-id])]
(when (and (not joined) (not spectated) (not spectating))
{:db (assoc-in db [:communities community-id :spectating] true)
:json-rpc/call [{:method "wakuext_spectateCommunity"
:params [community-id]
:on-success [:chat.ui/spectate-community-success]
:on-error (fn [err]
(log/error {:message
"Failed to spectate community"
:error err})
(rf/dispatch [:chat.ui/spectate-community-failed
community-id]))}]})))
(schema/=> spectate-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-id [:? :string]]]]]]
[:map
[:db map?]
[:json-rpc/call :schema.common/rpc-call]]])
(rf/reg-event-fx :chat.ui/spectate-community spectate-community)
(rf/defn save-link-preview-whitelist (rf/defn save-link-preview-whitelist
{:events [:chat.ui/link-preview-whitelist-received]} {:events [:chat.ui/link-preview-whitelist-received]}

View File

@ -0,0 +1,139 @@
(ns status-im.contexts.chat.messages.link-preview.events-test
(:require [cljs.test :as t]
[legacy.status-im.mailserver.core :as mailserver]
matcher-combinators.test
[status-im.contexts.chat.messages.link-preview.events :as sut]))
(t/deftest fetch-community
(t/testing "with community id"
(t/testing "update resolving indicator in db"
(t/is (match?
{:db {:communities/resolve-community-info {"community-id" true}}}
(sut/fetch-community {} ["community-id"]))))
(t/testing "call the fetch community rpc method with correct community id"
(t/is (match?
{:json-rpc/call [{:method "wakuext_fetchCommunity"
:params [{:CommunityKey "community-id"
:TryDatabase true
:WaitForResponse true}]}]}
(sut/fetch-community {} ["community-id"])))))
(t/testing "with nil community id"
(t/testing "do nothing"
(t/is (match?
nil
(sut/fetch-community {} nil))))))
(t/deftest community-failed-to-resolve
(t/testing "given a community id"
(t/testing "remove community id from resolving indicator in db"
(t/is (match?
nil
(get-in (sut/community-failed-to-resolve {:db {:communities/resolve-community-info
{"community-id" true}}}
["community-id"])
[:db :communities/resolve-community-info "community-id"]))))))
(t/deftest community-resolved
(with-redefs [sut/community-link (fn [id] (str "community-link+" id))]
(t/testing "given a community"
(let [cofx {:db {:communities/resolve-community-info {"community-id" true}}}
arg ["community-id" {:id "community-id"}]]
(t/testing "remove community id from resolving indicator in db"
(t/is (match?
nil
(get-in (sut/community-resolved cofx arg)
[:db :communities/resolve-community-info "community-id"]))))
(t/testing "dispatch fxs"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id "community-id"}]]]}
(sut/community-resolved cofx arg))))))
(t/testing "given a joined community"
(let [cofx {:db {:communities/resolve-community-info {"community-id" true}}}
arg ["community-id" {:id "community-id" :joined true}]]
(t/testing "dispatch fxs, do not spectate community"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id "community-id"}]]]}
(sut/community-resolved cofx arg))))))
(t/testing "given a token-gated community"
(let [cofx {:db {:communities/resolve-community-info {"community-id" true}}}
arg ["community-id" {:id "community-id" :tokenPermissions [1]}]]
(t/testing "dispatch fxs, do not spectate community"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id "community-id"}]]]}
(sut/community-resolved cofx arg))))))
(t/testing "given nil community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/community-resolved {} ["community-id" nil])))))))
(t/deftest spectate-community
(t/testing "given a joined community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community {:db {:communities {"community-id" {:joined true}}}}
["community-id"])))))
(t/testing "given a spectated community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community {:db {:communities {"community-id" {:spectated true}}}}
["community-id"])))))
(t/testing "given a spectating community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community {:db {:communities {"community-id" {:spectating true}}}}
["community-id"])))))
(t/testing "given a community"
(t/testing "mark community spectating"
(t/is (match?
{:db {:communities {"community-id" {:spectating true}}}}
(sut/spectate-community {:db {:communities {"community-id" {}}}} ["community-id"]))))
(t/testing "call spectate community rpc with correct community id"
(t/is (match?
{:json-rpc/call [{:method "wakuext_spectateCommunity"
:params ["community-id"]}]}
(sut/spectate-community {:db {:communities {"community-id" {}}}} ["community-id"]))))))
(t/deftest spectate-community-failed
(t/testing "mark community spectating false"
(t/is (match?
{:db {:communities {"community-id" {:spectating false}}}}
(sut/spectate-community-failed {} ["community-id"])))))
(t/deftest spectate-community-success
(t/testing "given communities"
(t/testing "mark first community spectating false"
(t/is (match?
{:db {:communities {"community-id" {:spectating false}}}}
(sut/spectate-community-success {} [{:communities [{:id "community-id"}]}]))))
(t/testing "mark first community spectated true"
(t/is (match?
{:db {:communities {"community-id" {:spectated true}}}}
(sut/spectate-community-success {} [{:communities [{:id "community-id"}]}]))))
(t/testing "dispatch fxs for first community"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch [::mailserver/request-messages]]]}
(sut/spectate-community-success {} [{:communities [{:id "community-id"}]}])))))
(t/testing "given empty community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community-success {} [{:communities []}])))))
(t/testing "given nil community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community-success {} []))))))

View File

@ -81,7 +81,7 @@
(fn [] (fn []
(when-not cached-preview-data (when-not cached-preview-data
(let [community-id (community-id-from-link community-link)] (let [community-id (community-id-from-link community-link)]
(rf/dispatch [:chat.ui/resolve-community-info community-id])))) (rf/dispatch [:chat.ui/fetch-community community-id]))))
:reagent-render :reagent-render
(fn [] (fn []
(when cached-preview-data (when cached-preview-data

View File

@ -63,10 +63,21 @@
{} {}
(:communityTokensMetadata c))))) (:communityTokensMetadata c)))))
(rf/defn handle-community (rf/reg-event-fx :communities/handle-community
[{:keys [db]} {:keys [id] :as community}] (fn [{:keys [db]}
(when id [community-js]]
{:db (assoc-in db [:communities id] (<-rpc community))})) (when community-js
(let [{:keys [token-permissions
token-permissions-check joined id]
:as community} (<-rpc community-js)
has-token-permissions? (not (seq token-permissions))]
{:db (assoc-in db [:communities id] community)
:fx [(when (and has-token-permissions? (not joined))
[:dispatch [:chat.ui/spectate-community id]])
(when (and has-token-permissions? (nil? token-permissions-check))
[:dispatch [:communities/check-permissions-to-join-community id]])
(when (and has-token-permissions? (not (get-in db [:community-channels-permissions id])))
[:dispatch [:communities/check-all-community-channels-permissions id]])]}))))
(rf/defn handle-removed-chats (rf/defn handle-removed-chats
[{:keys [db]} chat-ids] [{:keys [db]} chat-ids]
@ -109,10 +120,9 @@
(rf/defn handle-communities (rf/defn handle-communities
{:events [:community/fetch-success]} {:events [:community/fetch-success]}
[{:keys [db]} communities] [{:keys [db]} communities]
{:db (reduce (fn [db {:keys [id] :as community}] {:fx
(assoc-in db [:communities id] (<-rpc community))) (->> communities
db (map #(vector :dispatch [:communities/handle-community %])))})
communities)})
(rf/reg-event-fx :communities/request-to-join-result (rf/reg-event-fx :communities/request-to-join-result
(fn [{:keys [db]} [community-id request-id response-js]] (fn [{:keys [db]} [community-id request-id response-js]]
@ -138,7 +148,6 @@
:on-success #(rf/dispatch [:communities/request-to-join-result community-id request-id %]) :on-success #(rf/dispatch [:communities/request-to-join-result community-id request-id %])
:on-error #(log/error "failed to accept requests-to-join" community-id request-id %)}]})) :on-error #(log/error "failed to accept requests-to-join" community-id request-id %)}]}))
(rf/reg-event-fx :communities/get-user-requests-to-join-success (rf/reg-event-fx :communities/get-user-requests-to-join-success
(fn [{:keys [db]} [requests]] (fn [{:keys [db]} [requests]]
{:db (assoc db {:db (assoc db

View File

@ -8,41 +8,60 @@
(rf/reg-event-fx :communities/check-all-community-channels-permissions-success (rf/reg-event-fx :communities/check-all-community-channels-permissions-success
(fn [{:keys [db]} [community-id response]] (fn [{:keys [db]} [community-id response]]
{:db (assoc-in db {:db (-> db
[:community-channels-permissions community-id] (assoc-in [:community-channels-permissions community-id]
(data-store/rpc->channel-permissions (:channels response)))})) (data-store/rpc->channel-permissions (:channels response)))
(assoc-in [:communities community-id :checking-all-channels-permissions?] false))}))
(rf/reg-event-fx :communities/check-all-community-channels-permissions-failed
(fn [{:keys [db]} [community-id]]
{:db (assoc-in db [:communities community-id :checking-all-channels-permissions?] false)}))
(rf/reg-event-fx :communities/check-all-community-channels-permissions (rf/reg-event-fx :communities/check-all-community-channels-permissions
(fn [_ [community-id]] (fn [{:keys [db]} [community-id]]
{:fx [[:json-rpc/call (when (get-in db [:communities community-id])
{:db (assoc-in db [:communities community-id :checking-all-channels-permissions?] true)
:fx [[:json-rpc/call
[{:method "wakuext_checkAllCommunityChannelsPermissions" [{:method "wakuext_checkAllCommunityChannelsPermissions"
:params [{:CommunityID community-id}] :params [{:CommunityID community-id}]
:on-success [:communities/check-all-community-channels-permissions-success community-id] :on-success [:communities/check-all-community-channels-permissions-success community-id]
:on-error (fn [error] :on-error (fn [error]
(rf/dispatch [:communities/check-all-community-channels-permissions-failed
community-id])
(log/error "failed to check channels permissions" (log/error "failed to check channels permissions"
{:error error {:error error
:community-id community-id :community-id community-id
:event :event
:communities/check-all-community-channels-permissions}))}]]]})) :communities/check-all-community-channels-permissions}))}]]]})))
(rf/defn check-permissions-to-join-community-success (rf/reg-event-fx :communities/check-permissions-to-join-community-success
{:events [:communities/check-permissions-to-join-community-success]} (fn [{:keys [db]} [community-id result]]
[{:keys [db]} community-id result]
{:db (-> db {:db (-> db
(assoc-in [:communities community-id :checking-permissions?] false) (assoc-in [:communities community-id :checking-permissions?] false)
(assoc-in [:communities community-id :token-permissions-check] result))}) (assoc-in [:communities community-id :token-permissions-check] result))}))
(rf/defn check-permissions-to-join-community (rf/reg-event-fx :communities/check-permissions-to-join-community-failed
{:events [:communities/check-permissions-to-join-community]} (fn [{:keys [db]} [community-id]]
[{:keys [db]} community-id] {:db (assoc-in db [:communities community-id :checking-permissions?] false)}))
(rf/reg-event-fx :communities/check-permissions-to-join-community
(fn [{:keys [db]} [community-id]]
(when-let [community (get-in db [:communities community-id])]
(when-not (:checking-permissions? community)
{:db (-> db {:db (-> db
(assoc-in [:communities community-id :checking-permissions?] true) (assoc-in [:communities community-id :checking-permissions?] true)
(assoc-in [:communities community-id :can-request-access?] false)) (assoc-in [:communities community-id :can-request-access?] false))
:json-rpc/call [{:method "wakuext_checkPermissionsToJoinCommunity" :json-rpc/call [{:method "wakuext_checkPermissionsToJoinCommunity"
:params [{:communityId community-id}] :params [{:communityId community-id}]
:on-success #(rf/dispatch [:communities/check-permissions-to-join-community-success :on-success [:communities/check-permissions-to-join-community-success
community-id %]) community-id]
:on-error #(log/error "failed to request to join community" community-id %)}]}) :on-error (fn [err]
(rf/dispatch
[:communities/check-permissions-to-join-community-failed
community-id])
(log/error "failed to request to join community"
community-id
err))}]}))))
(defn request-to-join (defn request-to-join
[{:keys [db]} [{:keys [community-id password]}]] [{:keys [db]} [{:keys [community-id password]}]]

View File

@ -212,14 +212,14 @@
(defn add-handlers (defn add-handlers
[community-id [community-id
joined joined-or-spectated
{:keys [id locked?] {:keys [id locked?]
:or {locked? false} :or {locked? false}
:as chat}] :as chat}]
(merge (merge
chat chat
(when (and (not locked?) id) (when (and (not locked?) id)
{:on-press (when joined {:on-press (when joined-or-spectated
(fn [] (fn []
(rf/dispatch [:dismiss-keyboard]) (rf/dispatch [:dismiss-keyboard])
(debounce/dispatch-and-chill [:chat/navigate-to-chat (str community-id id)] (debounce/dispatch-and-chill [:chat/navigate-to-chat (str community-id id)]
@ -231,12 +231,12 @@
:community-id community-id}))) :community-id community-id})))
(defn add-handlers-to-chats (defn add-handlers-to-chats
[community-id joined chats] [community-id joined-or-spectated chats]
(mapv (partial add-handlers community-id joined) chats)) (mapv (partial add-handlers community-id joined-or-spectated) chats))
(defn add-handlers-to-categorized-chats (defn add-handlers-to-categorized-chats
[community-id categorized-chats joined] [community-id categorized-chats joined-or-spectated]
(let [add-on-press (partial add-handlers-to-chats community-id joined)] (let [add-on-press (partial add-handlers-to-chats community-id joined-or-spectated)]
(map (fn [[category v]] (map (fn [[category v]]
[category (update v :chats add-on-press)]) [category (update v :chats add-on-press)])
categorized-chats))) categorized-chats)))
@ -261,12 +261,13 @@
(defn community-content (defn community-content
[community] [community]
(rf/dispatch [:communities/check-all-community-channels-permissions (:id community)]) (rf/dispatch [:communities/check-all-community-channels-permissions (:id community)])
(fn [{:keys [name description joined images tags color id token-permissions] :as community} (fn [{:keys [name description joined spectated images tags color id token-permissions] :as community}
pending? pending?
{:keys [on-category-layout {:keys [on-category-layout
collapsed? collapsed?
on-first-channel-height-changed]}] on-first-channel-height-changed]}]
(let [chats-by-category (rf/sub [:communities/categorized-channels id])] (let [joined-or-spectated (or joined spectated)
chats-by-category (rf/sub [:communities/categorized-channels id])]
[:<> [:<>
[rn/view {:style style/community-content-container} [rn/view {:style style/community-content-container}
(when-not collapsed? (when-not collapsed?
@ -286,7 +287,7 @@
:community-id id :community-id id
:community-color color :community-color color
:on-first-channel-height-changed on-first-channel-height-changed} :on-first-channel-height-changed on-first-channel-height-changed}
(add-handlers-to-categorized-chats id chats-by-category joined)])]))) (add-handlers-to-categorized-chats id chats-by-category joined-or-spectated)])])))
(defn sticky-category-header (defn sticky-category-header
[_] [_]