diff --git a/src/quo/components/avatars/channel_avatar/view.cljs b/src/quo/components/avatars/channel_avatar/view.cljs index 7858bacd2e..d48c477ecb 100644 --- a/src/quo/components/avatars/channel_avatar/view.cljs +++ b/src/quo/components/avatars/channel_avatar/view.cljs @@ -12,7 +12,7 @@ (defn- initials [{:keys [full-name size customization-color theme]}] (let [amount-initials (if (#{:size-32 :size-64} size) 2 1) - channel-name (string/replace full-name "#" "")] + channel-name (utils.string/safe-replace full-name "#" "")] [text/text (cond-> {:accessibility-label :initials :style {:color (colors/resolve-color customization-color theme)} diff --git a/src/status_im/common/qr_codes/view.cljs b/src/status_im/common/qr_codes/view.cljs index a3da20fa1a..c43686db23 100644 --- a/src/status_im/common/qr_codes/view.cljs +++ b/src/status_im/common/qr_codes/view.cljs @@ -33,9 +33,12 @@ (let [qr-media-server-uri (image-server/get-qr-image-uri-for-any-url {:url url :port (rf/sub [:mediaserver/port]) - :qr-size (or 400 (int size)) + :qr-size (or (int size) 400) :error-level :highest})] - [quo/qr-code (assoc props :qr-image-uri qr-media-server-uri)])) + [quo/qr-code + (assoc props + :qr-image-uri + qr-media-server-uri)])) (defn get-network-short-name-url [network] diff --git a/src/status_im/contexts/communities/actions/chat/view.cljs b/src/status_im/contexts/communities/actions/chat/view.cljs index 2a171d1a07..e65c4218ff 100644 --- a/src/status_im/contexts/communities/actions/chat/view.cljs +++ b/src/status_im/contexts/communities/actions/chat/view.cljs @@ -94,10 +94,10 @@ :label (i18n/label :t/invite-people-from-contacts)}) (defn- action-qr-code - [] + [chat-id] {:icon :i/qr-code :accessibility-label :chat-show-qr-code - :on-press not-implemented/alert + :on-press #(rf/dispatch [:communities/share-community-channel-url-qr-code chat-id]) :label (i18n/label :t/show-qr)}) (defn- action-share @@ -115,7 +115,7 @@ [quo/action-drawer [[(action-invite-people) (action-token-requirements) - (action-qr-code) + (action-qr-code chat-id) (action-share chat-id)]]] (and (not inside-chat?) (not locked?)) @@ -126,7 +126,7 @@ (action-notification-settings) (action-pinned-messages) (action-invite-people) - (action-qr-code) + (action-qr-code chat-id) (action-share chat-id)]]] (and inside-chat? (not locked?)) @@ -139,7 +139,7 @@ (when config/fetch-messages-enabled? (chat-actions/fetch-messages chat-id)) (action-invite-people) - (action-qr-code) + (action-qr-code chat-id) (action-share chat-id)]]] :else nil))) diff --git a/src/status_im/contexts/communities/actions/share_community_channel/style.cljs b/src/status_im/contexts/communities/actions/share_community_channel/style.cljs new file mode 100644 index 0000000000..db71ed6f0d --- /dev/null +++ b/src/status_im/contexts/communities/actions/share_community_channel/style.cljs @@ -0,0 +1,35 @@ +(ns status-im.contexts.communities.actions.share-community-channel.style + (:require [quo.foundations.colors :as colors])) + +(def header-container + {:padding-horizontal 20 + :padding-vertical 12}) + +(def scan-notice + {:color colors/white-70-blur + :margin-top 16 + :margin-left :auto + :margin-right :auto}) + +(def qr-code-wrapper + {:padding-horizontal 20 + :margin-top 8 + :align-items :center}) + +(def gradient-cover-padding 20) +(def qr-code-padding 12) + +(defn qr-code-size + [total-width] + (- total-width (* gradient-cover-padding 2) (* qr-code-padding 2))) + +(defn gradient-cover-size + [total-width] + (- total-width (* gradient-cover-padding 2))) + +(defn gradient-cover-wrapper + [width] + {:width (gradient-cover-size width) + :position :absolute + :border-radius 12 + :z-index -1}) diff --git a/src/status_im/contexts/communities/actions/share_community_channel/view.cljs b/src/status_im/contexts/communities/actions/share_community_channel/view.cljs new file mode 100644 index 0000000000..58ba51592b --- /dev/null +++ b/src/status_im/contexts/communities/actions/share_community_channel/view.cljs @@ -0,0 +1,47 @@ +(ns status-im.contexts.communities.actions.share-community-channel.view + (:require + [quo.core :as quo] + [react-native.core :as rn] + [react-native.safe-area :as safe-area] + [status-im.common.qr-codes.view :as qr-codes] + [status-im.contexts.communities.actions.share-community-channel.style :as style] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) + +(defn view + [] + (fn [] + (let [{:keys [url chat-id]} (rf/sub [:get-screen-params]) + {:keys [color emoji chat-name]} (rf/sub [:chats/community-channel-ui-details-by-id chat-id]) + window-width (rf/sub [:dimensions/window-width])] + [quo/overlay {:type :shell} + [rn/view + {:style {:padding-top (safe-area/get-top)} + :key :share-community} + [quo/page-nav + {:icon-name :i/close + :on-press #(rf/dispatch [:navigate-back]) + :background :blur + :accessibility-label :top-bar}] + [quo/text-combinations + {:container-style style/header-container + :title (i18n/label :t/share-channel)}] + [rn/view {:style style/qr-code-wrapper} + [quo/gradient-cover + {:container-style + (style/gradient-cover-wrapper window-width) + :customization-color color}] + [rn/view + {:style {:padding-vertical 12}} + [qr-codes/qr-code + {:size (style/qr-code-size window-width) + :url url + :avatar :channel + :customization-color color + :emoji emoji + :full-name chat-name}]]] + [quo/text + {:size :paragraph-2 + :weight :regular + :style style/scan-notice} + (i18n/label :t/scan-with-status-app)]]]))) diff --git a/src/status_im/contexts/communities/events.cljs b/src/status_im/contexts/communities/events.cljs index b04be2b56e..67ece5168c 100644 --- a/src/status_im/contexts/communities/events.cljs +++ b/src/status_im/contexts/communities/events.cljs @@ -252,14 +252,23 @@ (get-in db [:communities community-id :previous-share-all-addresses?])) :fx [[:dispatch [:communities/check-permissions-to-join-community community-id]]]}))) -(rf/reg-event-fx :communities/share-community-channel-url-with-data - (fn [_ [chat-id]] - (let [{:keys [community-id channel-id]} (data-store.chats/decode-chat-id chat-id) - title (i18n/label :t/channel-on-status)] +(rf/reg-event-fx :communities/get-community-channel-share-data + (fn [_ [chat-id on-success]] + (let [{:keys [community-id channel-id]} (data-store.chats/decode-chat-id chat-id)] {:json-rpc/call [{:method "wakuext_shareCommunityChannelURLWithData" :params [{:CommunityID community-id :ChannelID channel-id}] - :on-success (fn [url] + :on-success on-success + :on-error (fn [err] + (log/error "failed to retrieve community channel url with data" + {:error err + :chat-id chat-id + :event :communities/get-community-channel-share-data}))}]}))) + +(rf/reg-event-fx :communities/share-community-channel-url-with-data + (fn [_ [chat-id]] + (let [title (i18n/label :t/channel-on-status) + on-success (fn [url] (share/open (if platform/ios? {:activityItemSources [{:placeholderItem {:type "text" @@ -271,12 +280,15 @@ :subject title :message url :url url - :isNewTask true}))) - :on-error (fn [err] - (log/error "failed to retrieve community channel url with data" - {:error err - :chat-id chat-id - :event "share-community-channel-url-with-data"}))}]}))) + :isNewTask true})))] + {:fx [[:dispatch [:communities/get-community-channel-share-data chat-id on-success]]]}))) + +(rf/reg-event-fx :communities/share-community-channel-url-qr-code + (fn [_ [chat-id]] + (let [on-success #(rf/dispatch [:open-modal :share-community-channel + {:chat-id chat-id + :url %}])] + {:fx [[:dispatch [:communities/get-community-channel-share-data chat-id on-success]]]}))) (rf/reg-event-fx :communities/set-airdrop-address (fn [{:keys [db]} [address community-id]] diff --git a/src/status_im/navigation/screens.cljs b/src/status_im/navigation/screens.cljs index 5d68915664..eda7697b44 100644 --- a/src/status_im/navigation/screens.cljs +++ b/src/status_im/navigation/screens.cljs @@ -16,6 +16,7 @@ addresses-for-permissions] [status-im.contexts.communities.actions.airdrop-addresses.view :as airdrop-addresses] [status-im.contexts.communities.actions.request-to-join.view :as join-menu] + [status-im.contexts.communities.actions.share-community-channel.view :as share-community-channel] [status-im.contexts.communities.discover.view :as communities.discover] [status-im.contexts.communities.overview.view :as communities.overview] [status-im.contexts.onboarding.create-password.view :as create-password] @@ -115,6 +116,10 @@ :options {:sheet? true} :component join-menu/view} + {:name :share-community-channel + :options options/transparent-screen-options + :component share-community-channel/view} + {:name :community-account-selection :options {:sheet? true} :component communities.accounts-selection/view} diff --git a/src/status_im/subs/chats.cljs b/src/status_im/subs/chats.cljs index c19a4c09c0..3dd2243a90 100644 --- a/src/status_im/subs/chats.cljs +++ b/src/status_im/subs/chats.cljs @@ -221,6 +221,16 @@ :community-id :emoji]))) +(re-frame/reg-sub + :chats/community-channel-ui-details-by-id + :<- [:chats/chats] + (fn [chats [_ chat-id]] + (select-keys + (get chats chat-id) + [:chat-name + :color + :emoji]))) + (re-frame/reg-sub :chats/current-chat-message-list-view-context :<- [:chats/current-chat-chat-view] diff --git a/src/status_im/subs/chats_test.cljs b/src/status_im/subs/chats_test.cljs index c2be6510e6..060675bba0 100644 --- a/src/status_im/subs/chats_test.cljs +++ b/src/status_im/subs/chats_test.cljs @@ -161,3 +161,19 @@ (is (not (:can-delete-message-for-everyone? (rf/sub [sub-name])))) (is (not (:group-admin? (rf/sub [sub-name])))) (is (not (:message-pin-enabled (rf/sub [sub-name]))))))) + +(h/deftest-sub :chats/community-channel-ui-details-by-id + [sub-name] + (testing "returns specific ui details of a given community channel chat id" + (let [chats {chat-id (assoc community-chat + :color :army + :emoji "๐Ÿ‘" + :chat-name "test")}] + (swap! rf-db/app-db assoc + :chats + chats) + (let [result (rf/sub [sub-name chat-id])] + (is (= 3 (count (keys result)))) + (is (= :army (:color result))) + (is (= "test" (:chat-name result))) + (is (= "๐Ÿ‘" (:emoji result))))))) diff --git a/translations/en.json b/translations/en.json index c76cccff9c..3e183d6483 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1260,6 +1260,7 @@ "scan-or-enter-sync-code": "Scan or enter sync code", "scan-qr": "Scan QR", "scan-qr-code": "Scan QR code", + "scan-with-status-app": "Scan with the Status app on another device", "invalid-qr": "Oops! This QR doesnโ€™t work with Status", "search": "Search", "search-discover-communities": "Search communities or categories",