diff --git a/desktop_files/.re-natal b/desktop_files/.re-natal index f63ff5865d..d945f2a81d 100644 --- a/desktop_files/.re-natal +++ b/desktop_files/.re-natal @@ -43,7 +43,6 @@ "react-native-image-crop-picker", "react-native-securerandom", "react-native-webview-bridge", - "react-native-fcm", "homoglyph-finder", "web3", "chance", diff --git a/desktop_files/package.json b/desktop_files/package.json index 0dc30daf8c..2053d4179e 100644 --- a/desktop_files/package.json +++ b/desktop_files/package.json @@ -51,7 +51,6 @@ "react-native-config": "git+https://github.com/status-im/react-native-config.git", "react-native-crypto": "2.1.1", "react-native-dialogs": "0.0.20", - "react-native-fcm": "10.0.3", "react-native-fetch-polyfill": "1.1.2", "react-native-fs": "git+https://github.com/status-im/react-native-fs.git", "react-native-http": "github:tradle/react-native-http#834492d", diff --git a/react-native/src/desktop/status_im/react_native/js_dependencies.cljs b/react-native/src/desktop/status_im/react_native/js_dependencies.cljs index c9598a680f..6523886f2c 100644 --- a/react-native/src/desktop/status_im/react_native/js_dependencies.cljs +++ b/react-native/src/desktop/status_im/react_native/js_dependencies.cljs @@ -12,7 +12,7 @@ (def EventEmmiter (js/require "react-native/Libraries/vendor/emitter/EventEmitter")) (def fetch (.-default (js/require "react-native-fetch-polyfill"))) (def i18n (js/require "react-native-i18n")) -(def react-native-firebase (js/require "react-native-firebase")) +(def react-native-firebase #js {}) (def camera #js {:constants {:Aspect "Portrait"}}) (def dialogs #js {}) (def dismiss-keyboard #js {}) diff --git a/src/status_im/ui/screens/accounts/login/models.cljs b/src/status_im/ui/screens/accounts/login/models.cljs index 1f19d102e6..a94d38288e 100644 --- a/src/status_im/ui/screens/accounts/login/models.cljs +++ b/src/status_im/ui/screens/accounts/login/models.cljs @@ -7,6 +7,7 @@ [status-im.utils.config :as config] [status-im.utils.keychain.core :as keychain] [status-im.utils.notifications :as notifications] + [status-im.utils.platform :as platform] [status-im.utils.universal-links.core :as universal-links])) ;;;; FX @@ -133,4 +134,4 @@ (when (not= view-id :create-account) [[:navigate-to-clean :home] (universal-links/stored-url-event cofx) - (notifications/stored-event address cofx)])]}) + (when-not platform/desktop? (notifications/stored-event address cofx))])]}) diff --git a/src/status_im/utils/notifications.cljs b/src/status_im/utils/notifications.cljs index b9ec989bf4..a2f780bc78 100644 --- a/src/status_im/utils/notifications.cljs +++ b/src/status_im/utils/notifications.cljs @@ -4,7 +4,6 @@ [status-im.utils.handlers-macro :as handlers-macro] [status-im.utils.handlers :as handlers] [status-im.react-native.js-dependencies :as rn] - [status-im.utils.platform :as platform] [status-im.ui.components.react :refer [copy-to-clipboard]] [taoensso.timbre :as log] [status-im.utils.platform :as platform])) @@ -12,175 +11,177 @@ ;; Work in progress namespace responsible for push notifications and interacting ;; with Firebase Cloud Messaging. -(handlers/register-handler-db - :update-fcm-token - (fn [db [_ fcm-token]] - (assoc-in db [:notifications :fcm-token] fcm-token))) +(when-not platform/desktop? -(handlers/register-handler-fx - :request-notifications-granted - (fn [_ _] - (re-frame/dispatch [:show-mainnet-is-default-alert]))) + (handlers/register-handler-db + :update-fcm-token + (fn [db [_ fcm-token]] + (assoc-in db [:notifications :fcm-token] fcm-token))) -(handlers/register-handler-fx - :request-notifications-denied - (fn [_ _] - (re-frame/dispatch [:show-mainnet-is-default-alert]))) + (handlers/register-handler-fx + :request-notifications-granted + (fn [_ _] + (re-frame/dispatch [:show-mainnet-is-default-alert]))) -(def firebase (object/get rn/react-native-firebase "default")) + (handlers/register-handler-fx + :request-notifications-denied + (fn [_ _] + (re-frame/dispatch [:show-mainnet-is-default-alert]))) -;; NOTE: Only need to explicitly request permissions on iOS. -(defn request-permissions [] - (if platform/desktop? - (re-frame/dispatch [:request-notifications-granted {}]) - (-> (.requestPermission (.messaging firebase)) - (.then - (fn [_] - (log/debug "notifications-granted") - (re-frame/dispatch [:request-notifications-granted {}])) - (fn [_] - (log/debug "notifications-denied") - (re-frame/dispatch [:request-notifications-denied {}])))))) + (def firebase (object/get rn/react-native-firebase "default")) -(defn get-fcm-token [] - (-> (.getToken (.messaging firebase)) - (.then (fn [x] - (log/debug "get-fcm-token: " x) - (re-frame/dispatch [:update-fcm-token x]))))) + ;; NOTE: Only need to explicitly request permissions on iOS. + (defn request-permissions [] + (if platform/desktop? + (re-frame/dispatch [:request-notifications-granted {}]) + (-> (.requestPermission (.messaging firebase)) + (.then + (fn [_] + (log/debug "notifications-granted") + (re-frame/dispatch [:request-notifications-granted {}])) + (fn [_] + (log/debug "notifications-denied") + (re-frame/dispatch [:request-notifications-denied {}])))))) -(defn on-refresh-fcm-token [] - (.onTokenRefresh (.messaging firebase) - (fn [x] - (log/debug "on-refresh-fcm-token: " x) - (re-frame/dispatch [:update-fcm-token x])))) + (defn get-fcm-token [] + (-> (.getToken (.messaging firebase)) + (.then (fn [x] + (log/debug "get-fcm-token: " x) + (re-frame/dispatch [:update-fcm-token x]))))) -;; TODO(oskarth): Only called in background on iOS right now. -;; NOTE(oskarth): Hardcoded data keys :sum and :msg in status-go right now. -(defn on-notification [] - (.onNotification (.notifications firebase) - (fn [event-js] - (let [event (js->clj event-js :keywordize-keys true) - data (select-keys event [:sum :msg]) - aps (:aps event)] - (log/debug "on-notification event: " (pr-str event)) - (log/debug "on-notification aps: " (pr-str aps)) - (log/debug "on-notification data: " (pr-str data)))))) + (defn on-refresh-fcm-token [] + (.onTokenRefresh (.messaging firebase) + (fn [x] + (log/debug "on-refresh-fcm-token: " x) + (re-frame/dispatch [:update-fcm-token x])))) -(def channel-id "status-im") -(def channel-name "Status") -(def sound-name "message.wav") -(def group-id "im.status.ethereum.MESSAGE") -(def icon "ic_stat_status_notification") + ;; TODO(oskarth): Only called in background on iOS right now. + ;; NOTE(oskarth): Hardcoded data keys :sum and :msg in status-go right now. + (defn on-notification [] + (.onNotification (.notifications firebase) + (fn [event-js] + (let [event (js->clj event-js :keywordize-keys true) + data (select-keys event [:sum :msg]) + aps (:aps event)] + (log/debug "on-notification event: " (pr-str event)) + (log/debug "on-notification aps: " (pr-str aps)) + (log/debug "on-notification data: " (pr-str data)))))) -(defn create-notification-channel [] - (let [channel (firebase.notifications.Android.Channel. channel-id - channel-name - firebase.notifications.Android.Importance.Max)] - (.setSound channel sound-name) - (.setShowBadge channel true) - (.enableVibration channel true) + (def channel-id "status-im") + (def channel-name "Status") + (def sound-name "message.wav") + (def group-id "im.status.ethereum.MESSAGE") + (def icon "ic_stat_status_notification") + + (defn create-notification-channel [] + (let [channel (firebase.notifications.Android.Channel. channel-id + channel-name + firebase.notifications.Android.Importance.Max)] + (.setSound channel sound-name) + (.setShowBadge channel true) + (.enableVibration channel true) + (.. firebase + notifications + -android + (createChannel channel) + (then #(log/debug "Notification channel created:" channel-id) + #(log/error "Notification channel creation error:" channel-id %))))) + + (defn store-event [{:keys [from to]} {:keys [db] :as cofx}] + (let [{:keys [address photo-path name]} (->> (get-in cofx [:db :accounts/accounts]) + vals + (filter #(= (:public-key %) to)) + first)] + (when address + {:db (assoc-in db [:push-notifications/stored to] from) + :dispatch [:open-login address photo-path name]}))) + + (defn process-initial-push-notification [{:keys [initial?]} {:keys [db]}] + (when initial? + {:db (assoc db :push-notifications/initial? true)})) + + (defn process-push-notification [{:keys [from to] :as event} {:keys [db] :as cofx}] + (let [current-public-key (get-in cofx [:db :current-public-key])] + (if current-public-key + (when (= to current-public-key) + {:db (update db :push-notifications/stored dissoc to) + :dispatch [:navigate-to-chat from]}) + (store-event event cofx)))) + + (defn handle-push-notification [cofx [_ event]] + (handlers-macro/merge-fx cofx + (process-initial-push-notification event) + (process-push-notification event))) + + (defn stored-event [address cofx] + (let [to (get-in cofx [:db :accounts/accounts address :public-key]) + from (get-in cofx [:db :push-notifications/stored to])] + (when from + [:handle-push-notification {:from from + :to to}]))) + + (defn parse-notification-payload [s] + (try + (js/JSON.parse s) + (catch :default _ + #js {}))) + + (defn handle-notification-event [event {:keys [initial?]}] + (let [msg (object/get (.. event -notification -data) "msg") + data (parse-notification-payload msg) + from (object/get data "from") + to (object/get data "to")] + (log/debug "on notification" (pr-str msg)) + (when (and from to) + (re-frame/dispatch [:handle-push-notification {:from from + :to to + :initial? initial?}])))) + + (defn on-notification-opened [] (.. firebase notifications - -android - (createChannel channel) - (then #(log/debug "Notification channel created:" channel-id) - #(log/error "Notification channel creation error:" channel-id %))))) + (onNotificationOpened handle-notification-event))) -(defn store-event [{:keys [from to]} {:keys [db] :as cofx}] - (let [{:keys [address photo-path name]} (->> (get-in cofx [:db :accounts/accounts]) - vals - (filter #(= (:public-key %) to)) - first)] - (when address - {:db (assoc-in db [:push-notifications/stored to] from) - :dispatch [:open-login address photo-path name]}))) + (def notification (firebase.notifications.Notification.)) -(defn process-initial-push-notification [{:keys [initial?]} {:keys [db]}] - (when initial? - {:db (assoc db :push-notifications/initial? true)})) + ;; API reference https://rnfirebase.io/docs/v4.2.x/notifications/reference/AndroidNotification + (defn display-notification [{:keys [title body from to]}] + (.. notification + (setTitle title) + (setBody body) + (setData (js/JSON.stringify #js {:from from + :to to})) + (setSound sound-name) + (-android.setChannelId channel-id) + (-android.setAutoCancel true) + (-android.setPriority firebase.notifications.Android.Priority.Max) + (-android.setGroup group-id) + (-android.setGroupSummary true) + (-android.setSmallIcon icon)) + (.. firebase + notifications + (displayNotification notification) + (then #(log/debug "Display Notification" title body)) + (then #(log/debug "Display Notification error" title body)))) -(defn process-push-notification [{:keys [from to] :as event} {:keys [db] :as cofx}] - (let [current-public-key (get-in cofx [:db :current-public-key])] - (if current-public-key - (when (= to current-public-key) - {:db (update db :push-notifications/stored dissoc to) - :dispatch [:navigate-to-chat from]}) - (store-event event cofx)))) + (re-frame/reg-fx :display-notification-fx display-notification) -(defn handle-push-notification [cofx [_ event]] - (handlers-macro/merge-fx cofx - (process-initial-push-notification event) - (process-push-notification event))) + (handlers/register-handler-fx :handle-push-notification handle-push-notification) -(defn stored-event [address cofx] - (let [to (get-in cofx [:db :accounts/accounts address :public-key]) - from (get-in cofx [:db :push-notifications/stored to])] - (when from - [:handle-push-notification {:from from - :to to}]))) + (re-frame/reg-fx + :handle-initial-push-notification-fx + (fn [{:keys [push-notifications/initial?]}] + (when-not initial? + (.. firebase + notifications + getInitialNotification + (then (fn [event] + (when event + (handle-notification-event event {:initial? true})))))))) -(defn parse-notification-payload [s] - (try - (js/JSON.parse s) - (catch :default _ - #js {}))) - -(defn handle-notification-event [event {:keys [initial?]}] - (let [msg (object/get (.. event -notification -data) "msg") - data (parse-notification-payload msg) - from (object/get data "from") - to (object/get data "to")] - (log/debug "on notification" (pr-str msg)) - (when (and from to) - (re-frame/dispatch [:handle-push-notification {:from from - :to to - :initial? initial?}])))) - -(defn on-notification-opened [] - (.. firebase - notifications - (onNotificationOpened handle-notification-event))) - -(def notification (firebase.notifications.Notification.)) - -;; API reference https://rnfirebase.io/docs/v4.2.x/notifications/reference/AndroidNotification -(defn display-notification [{:keys [title body from to]}] - (.. notification - (setTitle title) - (setBody body) - (setData (js/JSON.stringify #js {:from from - :to to})) - (setSound sound-name) - (-android.setChannelId channel-id) - (-android.setAutoCancel true) - (-android.setPriority firebase.notifications.Android.Priority.Max) - (-android.setGroup group-id) - (-android.setGroupSummary true) - (-android.setSmallIcon icon)) - (.. firebase - notifications - (displayNotification notification) - (then #(log/debug "Display Notification" title body)) - (then #(log/debug "Display Notification error" title body)))) - -(re-frame/reg-fx :display-notification-fx display-notification) - -(handlers/register-handler-fx :handle-push-notification handle-push-notification) - -(re-frame/reg-fx - :handle-initial-push-notification-fx - (fn [{:keys [push-notifications/initial?]}] - (when-not initial? - (.. firebase - notifications - getInitialNotification - (then (fn [event] - (when event - (handle-notification-event event {:initial? true})))))))) - -(defn init [] - (on-refresh-fcm-token) - (on-notification) - (on-notification-opened) - (when platform/android? - (create-notification-channel))) + (defn init [] + (on-refresh-fcm-token) + (on-notification) + (on-notification-opened) + (when platform/android? + (create-notification-channel))))