From 0675d0d8d767daa9c6950ce28b9a894ce9a564f8 Mon Sep 17 00:00:00 2001 From: Andrey Shovkoplyas Date: Fri, 12 Jun 2020 10:54:28 +0200 Subject: [PATCH] ios pn Signed-off-by: Andrea Maria Piana --- .env | 1 + .env.e2e | 1 + .env.jenkins | 1 + ios/Podfile.lock | 14 +- ios/StatusIm/AppDelegate.h | 3 +- ios/StatusIm/AppDelegate.m | 35 +++ package.json | 1 + resources/images/icons/tiny_muted@2x.png | Bin 0 -> 260 bytes resources/images/icons/tiny_muted@3x.png | Bin 0 -> 354 bytes src/mocks/js_dependencies.cljs | 2 + src/status_im/chat/models.cljs | 40 +++- src/status_im/chat/models_test.cljs | 4 +- src/status_im/data_store/chats.cljs | 6 +- src/status_im/ethereum/json_rpc.cljs | 40 +++- src/status_im/group_chats/core.cljs | 5 +- src/status_im/multiaccounts/core.cljs | 12 -- src/status_im/multiaccounts/create/core.cljs | 4 +- src/status_im/multiaccounts/login/core.cljs | 7 +- src/status_im/multiaccounts/logout/core.cljs | 4 +- src/status_im/multiaccounts/update/core.cljs | 7 + src/status_im/notifications/core.cljs | 202 +++++++++++++++++- src/status_im/subs.cljs | 3 + .../ui/components/chat_icon/screen.cljs | 2 +- .../ui/screens/home/views/inner_item.cljs | 13 +- .../screens/notifications_settings/views.cljs | 121 ++++++++++- .../ui/screens/profile/contact/views.cljs | 32 ++- .../ui/screens/profile/user/views.cljs | 26 ++- src/status_im/ui/screens/routing/main.cljs | 11 +- .../ui/screens/routing/profile_stack.cljs | 5 + src/status_im/utils/config.cljs | 1 + status-go-version.json | 6 +- test/appium/views/profile_view.py | 2 +- translations/en.json | 15 ++ yarn.lock | 7 + 34 files changed, 550 insertions(+), 83 deletions(-) create mode 100644 resources/images/icons/tiny_muted@2x.png create mode 100644 resources/images/icons/tiny_muted@3x.png diff --git a/.env b/.env index 91830fbf77..20fdd53690 100644 --- a/.env +++ b/.env @@ -24,3 +24,4 @@ QR_READ_TEST_MENU=1 ENABLE_ROOT_ALERT=1 ENABLE_REFERRAL_INVITE=1 ENABLE_QUO_PREVIEW=1 +APN_TOPIC=im.status.ethereum.pr diff --git a/.env.e2e b/.env.e2e index a9406ad94f..ea2482e0e0 100644 --- a/.env.e2e +++ b/.env.e2e @@ -23,3 +23,4 @@ KEYCARD_TEST_MENU=1 QR_READ_TEST_MENU=1 ENABLE_ROOT_ALERT=0 ENABLE_REFERRAL_INVITE=1 +APN_TOPIC=im.status.ethereum.pr diff --git a/.env.jenkins b/.env.jenkins index 0fc26e1316..ef5823a7b8 100644 --- a/.env.jenkins +++ b/.env.jenkins @@ -22,3 +22,4 @@ KEYCARD_TEST_MENU=0 ENABLE_ROOT_ALERT=1 ENABLE_REFERRAL_INVITE=1 DISABLE_WALLET_ON_MOBILE_NETWORK=1 +APN_TOPIC=im.status.ethereum.pr diff --git a/ios/Podfile.lock b/ios/Podfile.lock index a8418ad01e..7e9118cd63 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -328,6 +328,8 @@ PODS: - React - RNCMaskedView (0.1.9): - React + - RNCPushNotificationIOS (1.4.1): + - React - RNDeviceInfo (5.6.1): - React - RNFS (2.16.6): @@ -363,7 +365,7 @@ PODS: - SQLCipher/standard (3.4.2): - SQLCipher/common - SSZipArchive (2.2.3) - - TOCropViewController (2.5.3) + - TOCropViewController (2.5.4) - TouchID (4.4.1): - React - Yoga (1.14.0) @@ -435,6 +437,7 @@ DEPENDENCIES: - "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)" - "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)" - "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)" + - "RNCPushNotificationIOS (from `../node_modules/@react-native-community/push-notification-ios`)" - RNDeviceInfo (from `../node_modules/react-native-device-info`) - RNFS (from `../node_modules/react-native-fs`) - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) @@ -554,6 +557,8 @@ EXTERNAL SOURCES: :path: "../node_modules/@react-native-community/clipboard" RNCMaskedView: :path: "../node_modules/@react-native-community/masked-view" + RNCPushNotificationIOS: + :path: "../node_modules/@react-native-community/push-notification-ios" RNDeviceInfo: :path: "../node_modules/react-native-device-info" RNFS: @@ -596,7 +601,7 @@ SPEC CHECKSUMS: Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7 FlipperKit: afd4259ef9eadeeb2d30250b37d95cb3b6b97a69 Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51 - glog: 682164e7ac67e41afd8f7b6a37a96d04caf61cc0 + glog: 1f3da668190260b06b429bb211bfbee5cd790c28 OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355 Permission-Camera: afad27bf90337684d4a86f3825112d648c8c4d3b Permission-Microphone: 0ffabc3fe1c75cfb260525ee3f529383c9f4368c @@ -635,6 +640,7 @@ SPEC CHECKSUMS: RNCAsyncStorage: d059c3ee71738c39834a627476322a5a8cd5bf36 RNCClipboard: 8148e21ac347c51fd6cd4b683389094c216bb543 RNCMaskedView: 71fc32d971f03b7f03d6ab6b86b730c4ee64f5b6 + RNCPushNotificationIOS: c145c6253ea016e5efeff604f2720736b4a596f7 RNDeviceInfo: b6e650fbd234732c759544218657d549b4339038 RNFS: 2bd9eb49dc82fa9676382f0585b992c424cd59df RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38 @@ -648,11 +654,11 @@ SPEC CHECKSUMS: RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f SQLCipher: f9fcf29b2e59ced7defc2a2bdd0ebe79b40d4990 SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9 - TOCropViewController: 20a14b6a7a098308bf369e7c8d700dc983a974e6 + TOCropViewController: 2a1ae1242600b1f2d996fd91a5268b2309a33b5c TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4 Yoga: 3ebccbdd559724312790e7742142d062476b698e YogaKit: f782866e155069a2cca2517aafea43200b01fd5a PODFILE CHECKSUM: 5faa578ff5cb7a30abc18b9d620df288750a72fe -COCOAPODS: 1.9.1 +COCOAPODS: 1.9.3 diff --git a/ios/StatusIm/AppDelegate.h b/ios/StatusIm/AppDelegate.h index 90e4d6a2f6..912f523b96 100644 --- a/ios/StatusIm/AppDelegate.h +++ b/ios/StatusIm/AppDelegate.h @@ -9,8 +9,9 @@ #import #import +#import -@interface AppDelegate : UIResponder +@interface AppDelegate : UIResponder @property (nonatomic, strong) UIWindow *window; diff --git a/ios/StatusIm/AppDelegate.m b/ios/StatusIm/AppDelegate.m index 80a3ad11ac..0787c8ed96 100644 --- a/ios/StatusIm/AppDelegate.m +++ b/ios/StatusIm/AppDelegate.m @@ -20,6 +20,9 @@ #import #import +#import +#import + #if DEBUG #import #import @@ -88,6 +91,9 @@ static void InitializeFlipper(UIApplication *application) { [self.window makeKeyAndVisible]; [RNSplashScreen show]; + UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; + center.delegate = self; + return YES; } @@ -137,4 +143,33 @@ static void InitializeFlipper(UIApplication *application) { } } +// Required to register for notifications +- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings +{ + [RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings]; +} +// Required for the register event. +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken +{ + [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; +} +// Required for the registrationError event. +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error +{ + [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error]; +} +// IOS 10+ Required for localNotification event +- (void)userNotificationCenter:(UNUserNotificationCenter *)center +didReceiveNotificationResponse:(UNNotificationResponse *)response + withCompletionHandler:(void (^)(void))completionHandler +{ + [RNCPushNotificationIOS didReceiveNotificationResponse:response]; + completionHandler(); +} +// IOS 4-10 Required for the localNotification event. +- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification +{ + [RNCPushNotificationIOS didReceiveLocalNotification:notification]; +} + @end diff --git a/package.json b/package.json index 3055ed1b8b..811fdcab47 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@react-native-community/hooks": "^2.5.1", "@react-native-community/masked-view": "^0.1.6", "@react-native-community/netinfo": "^4.4.0", + "@react-native-community/push-notification-ios": "^1.4.1", "@react-native-community/slider": "^3.0.0", "@react-navigation/bottom-tabs": "^5.7.0", "@react-navigation/native": "^5.7.0", diff --git a/resources/images/icons/tiny_muted@2x.png b/resources/images/icons/tiny_muted@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe82c38a86f74f58bcb757db071d4260907ffce1 GIT binary patch literal 260 zcmV+f0sH=mP)kdg0002XNklAfXP31RPWXb$|pUR6-=YUOJtSA=w>rYnL1Fy@4!Q;7@C0 zuy5*^cp=2bOrKnt5V9f$B1(>D#*Kj64vWYo)wz3DT_-w&%{=*&r?IzL$;f+21u(B6PJj|MNeP<7WNfHkuDN%&+ zm7Rp~8!54Rj-TAdgUxL`XrAL|xAEZWHXbB}_)3QCXU4-j8IsS8hlLDjXU4-uMg)cU zZXg3@jd*w=1FjnJ@J0qCjd+;IfXEhwc-vj++3~P>j_=NH<6-d}-+lBP-(5Y&cURBx z-NkJ@d~zEPv)g#Mc#Ust)QsQQKrcj%6F2Sn&t#>et$sX6qV-ytD2WGwt^bIxWIz_i zcP0c1Zn@}?#PI;!*z###p4dQ!#McpPF&GR6oi6Jf9!~g&Q07*qoM6N<$f_{>l AQ~&?~ literal 0 HcmV?d00001 diff --git a/src/mocks/js_dependencies.cljs b/src/mocks/js_dependencies.cljs index 00ebac51af..22cf279737 100644 --- a/src/mocks/js_dependencies.cljs +++ b/src/mocks/js_dependencies.cljs @@ -190,6 +190,7 @@ #js {:localNotification identity :requestPermission identity}) +(def push-notification-ios #js {}) ;; Update i18n_resources.cljs (defn mock [module] (case module @@ -219,6 +220,7 @@ "react-native-haptic-feedback" react-native-haptic-feedback "react-native-device-info" react-native-device-info "react-native-push-notification" react-native-push-notification + "@react-native-community/push-notification-ios" push-notification-ios "./fleets.js" default-fleets "./chats.js" default-chats "../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json")) diff --git a/src/status_im/chat/models.cljs b/src/status_im/chat/models.cljs index aee372f4df..26272b91b9 100644 --- a/src/status_im/chat/models.cljs +++ b/src/status_im/chat/models.cljs @@ -1,5 +1,6 @@ (ns status-im.chat.models (:require [re-frame.core :as re-frame] + [taoensso.timbre :as log] [status-im.multiaccounts.model :as multiaccounts.model] [status-im.transport.filters.core :as transport.filters] [status-im.contact.core :as contact.core] @@ -136,15 +137,15 @@ (fx/defn upsert-chat "Upsert chat when not deleted" - [{:keys [db] :as cofx} {:keys [chat-id] :as chat-props}] + [{:keys [db] :as cofx} {:keys [chat-id] :as chat-props} on-success] (fx/merge cofx (ensure-chat chat-props) - #(chats-store/save-chat % (get-in % [:db :chats chat-id])))) + #(chats-store/save-chat % (get-in % [:db :chats chat-id]) on-success))) (fx/defn handle-save-chat {:events [::save-chat]} - [{:keys [db] :as cofx} chat-id] - (chats-store/save-chat cofx (get-in db [:chats chat-id]))) + [{:keys [db] :as cofx} chat-id on-success] + (chats-store/save-chat cofx (get-in db [:chats chat-id]) on-success)) (fx/defn handle-mark-all-read-successful {:events [::mark-all-read-successful]} @@ -172,7 +173,8 @@ :public? true :might-have-join-time-messages? true :unviewed-messages-count 0 - :loaded-unviewed-messages-ids #{}})) + :loaded-unviewed-messages-ids #{}} + nil)) (fx/defn clear-history "Clears history of the particular chat" @@ -192,7 +194,7 @@ :unviewed-messages-count 0 :deleted-at-clock-value last-message-clock-value}))} (messages-store/delete-messages-by-chat-id chat-id) - #(chats-store/save-chat % (get-in % [:db :chats chat-id]))))) + #(chats-store/save-chat % (get-in % [:db :chats chat-id]) nil)))) (fx/defn deactivate-chat "Deactivate chat in db, no side effects" @@ -253,7 +255,8 @@ (when (not= (multiaccounts.model/current-public-key cofx) chat-id) (fx/merge cofx (upsert-chat {:chat-id chat-id - :is-active true}) + :is-active true} + nil) (transport.filters/load-chat chat-id) (navigate-to-chat chat-id)))) @@ -293,6 +296,29 @@ {:db (assoc db :contacts/identity identity)} (navigation/navigate-to-cofx :profile nil))))) +(fx/defn mute-chat-failed + {:events [::mute-chat-failed]} + [{:keys [db] :as cofx} chat-id muted? error] + (log/error "mute chat failed" chat-id error) + {:db (assoc-in db [:chats chat-id :muted] (not muted?))}) + +(fx/defn mute-chat + {:events [::mute-chat-toggled]} + [{:keys [db] :as cofx} chat-id muted?] + (let [method (if muted? "muteChat" "unmuteChat") + chat (get-in db [:chats chat-id])] + ;; chat does not exist, create and then mute + (if-not chat + (upsert-chat cofx + {:is-active true + :chat-id chat-id} + #(re-frame/dispatch [::mute-chat-toggled chat-id muted?])) + {:db (assoc-in db [:chats chat-id :muted] muted?) + ::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) method) + :params [chat-id] + :on-error #(re-frame/dispatch [::mute-chat-failed chat-id muted? %]) + :on-success #(log/info method "successful" chat-id)}]}))) + (fx/defn show-profile {:events [:chat.ui/show-profile]} [cofx identity] diff --git a/src/status_im/chat/models_test.cljs b/src/status_im/chat/models_test.cljs index 8fde8b7aba..23f7b186d8 100644 --- a/src/status_im/chat/models_test.cljs +++ b/src/status_im/chat/models_test.cljs @@ -15,7 +15,7 @@ cofx {:now "now" :db {:contacts/contacts {chat-id {:name contact-name}}}} - response (chat/upsert-chat cofx chat-props) + response (chat/upsert-chat cofx chat-props nil) actual-chat (get-in response [:db :chats chat-id])] (testing "it adds the chat to the chats collection" (is actual-chat)) @@ -36,7 +36,7 @@ :extra-prop "some"} cofx {:db {:chats {chat-id {:is-active true :name "old-name"}}}} - response (chat/upsert-chat cofx chat-props) + response (chat/upsert-chat cofx chat-props nil) actual-chat (get-in response [:db :chats chat-id])] (testing "it adds the chat to the chats collection" (is actual-chat)) diff --git a/src/status_im/data_store/chats.cljs b/src/status_im/data_store/chats.cljs index b1c67fe519..8e9678f62e 100644 --- a/src/status_im/data_store/chats.cljs +++ b/src/status_im/data_store/chats.cljs @@ -94,10 +94,12 @@ (update :last-message #(when % (messages/<-rpc %))) (dissoc :chatType :members))) -(fx/defn save-chat [cofx {:keys [chat-id] :as chat}] +(fx/defn save-chat [cofx {:keys [chat-id] :as chat} on-success] {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "saveChat") :params [(->rpc chat)] - :on-success #(log/debug "saved chat" chat-id "successfuly") + :on-success #(do + (log/debug "saved chat" chat-id "successfuly") + (when on-success (on-success))) :on-failure #(log/error "failed to save chat" chat-id %)}]}) (fx/defn fetch-chats-rpc [cofx {:keys [on-success]}] diff --git a/src/status_im/ethereum/json_rpc.cljs b/src/status_im/ethereum/json_rpc.cljs index afba343ac0..06c3b1784a 100644 --- a/src/status_im/ethereum/json_rpc.cljs +++ b/src/status_im/ethereum/json_rpc.cljs @@ -71,6 +71,8 @@ "shhext_updateMessageOutgoingStatus" {} "shhext_chatMessages" {} "shhext_saveChat" {} + "shhext_muteChat" {} + "shhext_unmuteChat" {} "shhext_contacts" {} "shhext_prepareContent" {} "shhext_blockContact" {} @@ -93,6 +95,18 @@ "shhext_sendGroupChatInvitationRequest" {} "shhext_sendGroupChatInvitationRejection" {} "shhext_getGroupChatInvitations" {} + "shhext_registerForPushNotifications" {} + "shhext_unregisterFromPushNotifications" {} + "shhext_enablePushNotificationsFromContactsOnly" {} + "shhext_disablePushNotificationsFromContactsOnly" {} + "shhext_startPushNotificationsServer" {} + "shhext_stopPushNotificationsServer" {} + "shhext_disableSendingNotifications" {} + "shhext_enableSendingNotifications" {} + "shhext_addPushNotificationsServer" {} + "shhext_getPushNotificationsServers" {} + "shhext_enablePushNotificationsBlockMentions" {} + "shhext_disablePushNotificationsBlockMentions" {} "wakuext_post" {} "wakuext_startMessenger" {} "wakuext_sendPairInstallation" {} @@ -130,6 +144,8 @@ "wakuext_updateMessageOutgoingStatus" {} "wakuext_chatMessages" {} "wakuext_saveChat" {} + "wakuext_muteChat" {} + "wakuext_unmuteChat" {} "wakuext_contacts" {} "wakuext_prepareContent" {} "wakuext_blockContact" {} @@ -152,6 +168,18 @@ "wakuext_sendGroupChatInvitationRequest" {} "wakuext_sendGroupChatInvitationRejection" {} "wakuext_getGroupChatInvitations" {} + "wakuext_registerForPushNotifications" {} + "wakuext_unregisterFromPushNotifications" {} + "wakuext_enablePushNotificationsFromContactsOnly" {} + "wakuext_disablePushNotificationsFromContactsOnly" {} + "wakuext_startPushNotificationsServer" {} + "wakuext_stopPushNotificationsServer" {} + "wakuext_disableSendingNotifications" {} + "wakuext_enableSendingNotifications" {} + "wakuext_addPushNotificationsServer" {} + "wakuext_getPushNotificationsServers" {} + "wakuext_enablePushNotificationsBlockMentions" {} + "wakuext_disablePushNotificationsBlockMentions" {} "status_chats" {} "wallet_getTransfers" {} "wallet_getTokensBalances" {} @@ -210,16 +238,20 @@ (str "shhext_" method))) (defn call - [{:keys [method params on-success] :as arg}] + [{:keys [method params on-success on-error] :as arg}] (if-let [method-options (json-rpc-api method)] (let [params (or params []) {:keys [id on-result subscription?] :or {on-result identity id 1}} method-options - on-error (or (on-error-retry call arg) - #(log/warn :json-rpc/error method :error % :params params))] + on-error (or + on-error + (on-error-retry call arg) + #(log/warn :json-rpc/error method :error % :params params))] (if (nil? method) - (log/error :json-rpc/method-not-found method) + (do + (log/error :json-rpc/method-not-found method) + (on-error :json-rpc/method-not-found)) (status/call-private-rpc (types/clj->json {:jsonrpc "2.0" :id id diff --git a/src/status_im/group_chats/core.cljs b/src/status_im/group_chats/core.cljs index e8828ba854..eb300c382d 100644 --- a/src/status_im/group_chats/core.cljs +++ b/src/status_im/group_chats/core.cljs @@ -117,7 +117,8 @@ (fx/merge cofx (models.chat/deactivate-chat chat-id) (models.chat/upsert-chat {:chat-id chat-id - :is-active false}) + :is-active false} + nil) (navigation/navigate-to-cofx :home {}))) (defn- valid-name? [name] @@ -167,4 +168,4 @@ {:db (update db :group-chat/invitations #(reduce (fn [acc {:keys [id] :as inv}] (assoc acc id inv)) % - invitations))}) \ No newline at end of file + invitations))}) diff --git a/src/status_im/multiaccounts/core.cljs b/src/status_im/multiaccounts/core.cljs index a3b8a017be..c940a672bf 100644 --- a/src/status_im/multiaccounts/core.cljs +++ b/src/status_im/multiaccounts/core.cljs @@ -3,7 +3,6 @@ [status-im.ethereum.stateofus :as stateofus] [status-im.multiaccounts.update.core :as multiaccounts.update] [status-im.native-module.core :as native-module] - [status-im.notifications.core :as notifications] [status-im.utils.fx :as fx] [status-im.utils.gfycat.core :as gfycat] [status-im.utils.identicon :as identicon] @@ -87,17 +86,6 @@ :dev-mode? dev-mode? {})) -(fx/defn switch-notifications - {:events [:multiaccounts.ui/notifications-switched]} - [cofx notifications-enabled?] - (fx/merge cofx - {(if notifications-enabled? - ::notifications/enable - ::notifications/disable) nil} - (multiaccounts.update/multiaccount-update - :notifications-enabled? (boolean notifications-enabled?) - {}))) - (fx/defn switch-chaos-mode [{:keys [db] :as cofx} chaos-mode?] (when (:multiaccount db) diff --git a/src/status_im/multiaccounts/create/core.cljs b/src/status_im/multiaccounts/create/core.cljs index 509c713ba1..f319f10a3a 100644 --- a/src/status_im/multiaccounts/create/core.cljs +++ b/src/status_im/multiaccounts/create/core.cljs @@ -138,8 +138,7 @@ [{:keys [db] :as cofx}] (fx/merge cofx {:db (dissoc db :intro-wizard)} - (navigation/navigate-to-cofx (if platform/android? - :notifications-settings :welcome) nil))) + (navigation/navigate-to-cofx :notifications-onboarding nil))) (fx/defn init-key-generation [{:keys [db] :as cofx}] @@ -252,6 +251,7 @@ :dapps-address (:address wallet-account) :latest-derived-path 0 :signing-phrase signing-phrase + :send-push-notifications? true :installation-id (random-guid-generator)} constants/default-multiaccount) ;; The address from which we derive any chat diff --git a/src/status_im/multiaccounts/login/core.cljs b/src/status_im/multiaccounts/login/core.cljs index 5a5b6426a4..f7ed0c70de 100644 --- a/src/status_im/multiaccounts/login/core.cljs +++ b/src/status_im/multiaccounts/login/core.cljs @@ -22,7 +22,6 @@ [status-im.utils.identicon :as identicon] [status-im.utils.keychain.core :as keychain] [status-im.utils.logging.core :as logging] - [status-im.utils.platform :as platform] [status-im.utils.security :as security] [status-im.utils.types :as types] [status-im.utils.utils :as utils] @@ -88,8 +87,7 @@ {:db (update db :keycard dissoc :flow)} (if (= :import flow) (navigation/navigate-to-cofx :intro-stack {:screen :keycard-recovery-success}) - (navigation/navigate-to-cofx (if platform/android? - :notifications-settings :welcome) nil)))))) + (navigation/navigate-to-cofx :notifications-onboarding nil)))))) (fx/defn initialize-dapp-permissions {:events [::initialize-dapp-permissions]} @@ -192,8 +190,7 @@ (fn [accounts custom-tokens] (re-frame/dispatch [::initialize-wallet accounts custom-tokens]))} - (and platform/android? - notifications-enabled?) + notifications-enabled? (assoc ::notifications/enable nil)) (acquisition/login) (initialize-appearance) diff --git a/src/status_im/multiaccounts/logout/core.cljs b/src/status_im/multiaccounts/logout/core.cljs index 2b40c4f1cc..6004ec3074 100644 --- a/src/status_im/multiaccounts/logout/core.cljs +++ b/src/status_im/multiaccounts/logout/core.cljs @@ -6,7 +6,8 @@ [status-im.native-module.core :as status] [status-im.transport.core :as transport] [status-im.utils.fx :as fx] - [status-im.utils.keychain.core :as keychain])) + [status-im.utils.keychain.core :as keychain] + [status-im.notifications.core :as notifications])) (fx/defn logout-method [{:keys [db] :as cofx} {:keys [auth-method logout?]}] @@ -15,6 +16,7 @@ {::logout nil :keychain/clear-user-password key-uid ::init/open-multiaccounts #(re-frame/dispatch [::init/initialize-multiaccounts % {:logout? logout?}])} + (notifications/logout-disable) (keychain/save-auth-method key-uid auth-method) (transport/stop-whisper) (chaos-mode/stop-checking) diff --git a/src/status_im/multiaccounts/update/core.cljs b/src/status_im/multiaccounts/update/core.cljs index 19477b4d0e..43087aaaad 100644 --- a/src/status_im/multiaccounts/update/core.cljs +++ b/src/status_im/multiaccounts/update/core.cljs @@ -39,3 +39,10 @@ (multiaccount-update cofx :mnemonic nil {})) + +(fx/defn optimistic + [{:keys [db] :as cofx} setting setting-value] + (let [current-multiaccount (:multiaccount db)] + {:db (if setting-value + (assoc-in db [:multiaccount setting] setting-value) + (update db :multiaccount dissoc setting))})) diff --git a/src/status_im/notifications/core.cljs b/src/status_im/notifications/core.cljs index 228240a4c5..bc7c82fb86 100644 --- a/src/status_im/notifications/core.cljs +++ b/src/status_im/notifications/core.cljs @@ -2,7 +2,48 @@ (:require [re-frame.core :as re-frame] [taoensso.timbre :as log] [status-im.utils.fx :as fx] - [status-im.native-module.core :as status])) + [status-im.multiaccounts.update.core :as multiaccounts.update] + ["@react-native-community/push-notification-ios" :default pn-ios] + [status-im.native-module.core :as status] + [quo.platform :as platform] + [status-im.utils.config :as config] + [status-im.ethereum.json-rpc :as json-rpc] + [status-im.waku.core :as waku])) + +(def server-type-default 1) +(def server-type-custom 2) + +(def apn-token-type 1) +(def firebase-token-type 2) +(def listeners-added? (atom nil)) +(defn server<-rpc [{:keys [type publicKey registered]}] + {:public-key publicKey + :type type + :registered registered}) + +(defn add-event-listeners [] + (when-not @listeners-added? + (reset! listeners-added? true) + (.addEventListener + ^js pn-ios + "register" + (fn [token] + (re-frame/dispatch [::registered-for-push-notifications token]))) + (.addEventListener + ^js pn-ios + "registrationError" + (fn [error] + (re-frame/dispatch [::switch-error true error]))))) + +(defn enable-ios-notifications [] + (add-event-listeners) + (-> (.requestPermissions ^js pn-ios) + (.then #()) + (.catch #()))) + +(defn disable-ios-notifications [] + (.abandonPermissions ^js pn-ios) + (re-frame/dispatch [::unregistered-from-push-notifications])) ;; FIXME: Repalce with request permission from audio messages PR lib (re-frame/reg-fx @@ -23,9 +64,164 @@ (re-frame/reg-fx ::enable (fn [_] - (status/enable-notifications))) + (if platform/android? + (status/enable-notifications) + (enable-ios-notifications)))) (re-frame/reg-fx ::disable (fn [_] - (status/disable-notifications))) + (if platform/android? + (status/disable-notifications) + (disable-ios-notifications)))) + +(re-frame/reg-fx + ::logout-disable + (fn [_] + (if platform/android? + (status/disable-notifications) + (.abandonPermissions ^js pn-ios)))) + +(fx/defn handle-enable-notifications-event + {:events [::registered-for-push-notifications]} + [cofx token] + {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "registerForPushNotifications") + :params [token (if platform/ios? config/apn-topic) (if platform/ios? apn-token-type firebase-token-type)] + :on-success #(log/info "[push-notifications] register-success" %) + :on-error #(re-frame/dispatch [::switch-error true %])}]}) + +(fx/defn handle-disable-notifications-event + {:events [::unregistered-from-push-notifications]} + [cofx] + {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "unregisterFromPushNotifications") + :params [] + :on-success #(log/info "[push-notifications] unregister-success" %) + :on-error #(re-frame/dispatch [::switch-error false %])}]}) + +(fx/defn logout-disable + [cofx] + (merge {::logout-disable nil} + (when platform/ios? + {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "unregisterFromPushNotifications") + :params [] + :on-success #(log/info "[push-notifications] unregister-success" %) + :on-error #(log/info "[push-notifications] unregister-error" %)}]}))) + +(fx/defn notification-switch-error + {:events [::switch-error]} + [cofx enabled?] + (if platform/android? + (multiaccounts.update/multiaccount-update + :notifications-enabled? (not enabled?) + {}) + (multiaccounts.update/optimistic cofx :remote-push-notifications-enabled? (not (boolean enabled?))))) + +(fx/defn notification-switch + {:events [::switch]} + [{:keys [db] :as cofx} enabled?] + (fx/merge cofx + (if enabled? + {::enable nil} + {::disable nil}) + (if platform/android? + (multiaccounts.update/multiaccount-update + :notifications-enabled? enabled? + {}) + (multiaccounts.update/optimistic :remote-push-notifications-enabled? (boolean enabled?))))) + +(fx/defn notification-non-contacts-error + {:events [::non-contacts-update-error]} + [cofx enabled?] + (multiaccounts.update/optimistic cofx :push-notifications-from-contacts-only? (not (boolean enabled?)))) + +(fx/defn notification-block-mentions-error + {:events [::block-mentions-update-error]} + [cofx enabled?] + (multiaccounts.update/optimistic cofx :push-notifications-block-mentions? (not (boolean enabled?)))) + +(fx/defn notification-non-contacts + {:events [::switch-non-contacts]} + [{:keys [db] :as cofx} enabled?] + (let [method (if enabled? + "enablePushNotificationsFromContactsOnly" + "disablePushNotificationsFromContactsOnly")] + (fx/merge cofx + {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) method) + :params [] + :on-success #(log/info "[push-notifications] contacts-notification-success" %) + :on-error #(re-frame/dispatch [::non-contacts-update-error enabled? %])}]} + + (multiaccounts.update/optimistic :push-notifications-from-contacts-only? (boolean enabled?))))) + +(fx/defn notification-block-mentions + {:events [::switch-block-mentions]} + [{:keys [db] :as cofx} enabled?] + (let [method (if enabled? + "enablePushNotificationsBlockMentions" + "disablePushNotificationsBlockMentions")] + (log/info "USING METHOD" method enabled?) + (fx/merge cofx + {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) method) + :params [] + :on-success #(log/info "[push-notifications] block-mentions-success" %) + :on-error #(re-frame/dispatch [::block-mentions-update-error enabled? %])}]} + + (multiaccounts.update/optimistic :push-notifications-block-mentions? (boolean enabled?))))) + +(fx/defn switch-push-notifications-server-enabled + {:events [::switch-push-notifications-server-enabled]} + [{:keys [db] :as cofx} enabled?] + (let [method (if enabled? + "startPushNotificationsServer" + "stopPushNotificationsServer")] + (fx/merge cofx + {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) method) + :params [] + :on-success #(log/info "[push-notifications] switch-server-enabled successful" %) + :on-error #(re-frame/dispatch [::push-notifications-server-update-error enabled? %])}]} + + (multiaccounts.update/optimistic :push-notifications-server-enabled? (boolean enabled?))))) + +(fx/defn switch-send-notifications + {:events [::switch-send-push-notifications]} + [{:keys [db] :as cofx} enabled?] + (let [method (if enabled? + "enableSendingNotifications" + "disableSendingNotifications")] + (fx/merge cofx + {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) method) + :params [] + :on-success #(log/info "[push-notifications] switch-send-notifications successful" %) + :on-error #(re-frame/dispatch [::push-notifications-send-update-error enabled? %])}]} + + (multiaccounts.update/optimistic :send-push-notifications? (boolean enabled?))))) + +(fx/defn handle-add-server-error + {:events [::push-notifications-add-server-error]} + [_ public-key error] + (log/error "failed to add server", public-key, error)) + +(fx/defn add-server + {:events [::add-server]} + [{:keys [db] :as cofx} public-key] + (fx/merge cofx + {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "addPushNotificationsServer") + :params [public-key] + :on-success #(do + (log/info "[push-notifications] switch-send-notifications successful" %) + (re-frame/dispatch [::fetch-servers])) + :on-error #(re-frame/dispatch [::push-notifications-add-server-error public-key %])}]})) + +(fx/defn handle-servers-fetched + {:events [::servers-fetched]} + [{:keys [db]} servers] + {:db (assoc db :push-notifications/servers (map server<-rpc servers))}) + +(fx/defn fetch-push-notifications-servers + {:events [::fetch-servers]} + [cofx] + {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "getPushNotificationsServers") + :params [] + :on-success #(do + (log/info "[push-notifications] servers fetched" %) + (re-frame/dispatch [::servers-fetched %]))}]}) diff --git a/src/status_im/subs.cljs b/src/status_im/subs.cljs index f042c27212..124d67ddf5 100644 --- a/src/status_im/subs.cljs +++ b/src/status_im/subs.cljs @@ -197,6 +197,9 @@ ;; delete profile (reg-root-key-sub :delete-profile/error :delete-profile/error) +;; push notifications +(reg-root-key-sub :push-notifications/servers :push-notifications/servers) + ;;GENERAL ============================================================================================================== (re-frame/reg-sub diff --git a/src/status_im/ui/components/chat_icon/screen.cljs b/src/status_im/ui/components/chat_icon/screen.cljs index f9333bf869..7b67bc8083 100644 --- a/src/status_im/ui/components/chat_icon/screen.cljs +++ b/src/status_im/ui/components/chat_icon/screen.cljs @@ -132,4 +132,4 @@ [react/i18n-text {:style styles/profile-icon-edit-text :key :edit}]]) (if (and photo-path (seq photo-path)) [photos/photo photo-path styles] - [default-chat-icon name styles])])) \ No newline at end of file + [default-chat-icon name styles])])) diff --git a/src/status_im/ui/screens/home/views/inner_item.cljs b/src/status_im/ui/screens/home/views/inner_item.cljs index b867c27416..d96aa4a46d 100644 --- a/src/status_im/ui/screens/home/views/inner_item.cljs +++ b/src/status_im/ui/screens/home/views/inner_item.cljs @@ -124,7 +124,7 @@ :accessibility-label :unviewed-messages-public}] [badge/message-counter unviewed-messages-count])])) -(defn icon-style [] +(def icon-style {:color colors/black :width 15 :height 15 @@ -134,7 +134,7 @@ (defn home-list-item [home-item] (let [{:keys [chat-id chat-name color online group-chat - public? timestamp last-message]} + public? timestamp last-message muted]} home-item private-group? (and group-chat (not public?)) public-group? (and group-chat public?)] @@ -148,13 +148,16 @@ :padding-right 16 :align-items :center} (cond + muted + [icons/icon :main-icons/tiny-muted (assoc icon-style :color colors/gray)] private-group? - [icons/icon :main-icons/tiny-group (icon-style)] + [icons/icon :main-icons/tiny-group icon-style] public-group? - [icons/icon :main-icons/tiny-public (icon-style)] + [icons/icon :main-icons/tiny-public icon-style] :else - [icons/icon :main-icons/tiny-new-contact (icon-style)]) + [icons/icon :main-icons/tiny-new-contact icon-style]) [quo/text {:weight :medium + :color (when muted :secondary) :accessibility-label :chat-name-text :ellipsize-mode :tail :number-of-lines 1} diff --git a/src/status_im/ui/screens/notifications_settings/views.cljs b/src/status_im/ui/screens/notifications_settings/views.cljs index 480ca78a5d..9120551474 100644 --- a/src/status_im/ui/screens/notifications_settings/views.cljs +++ b/src/status_im/ui/screens/notifications_settings/views.cljs @@ -1,12 +1,84 @@ (ns status-im.ui.screens.notifications-settings.views - (:require [status-im.ui.components.colors :as colors] - [status-im.ui.components.react :as react] - [status-im.react-native.resources :as resources] + (:require-macros [status-im.utils.views :refer [defview letsubs]]) + (:require [re-frame.core :as re-frame] + [reagent.core :as reagent] + [status-im.i18n :as i18n] [quo.core :as quo] - [re-frame.core :as re-frame] - [status-im.i18n :as i18n])) + [quo.design-system.colors :as quo-colors] + [status-im.notifications.core :as notifications] + [status-im.ui.components.colors :as colors] + [status-im.react-native.resources :as resources] + [status-im.ui.components.react :as react] + [status-im.ui.components.topbar :as topbar])) + +(defonce server (reagent/atom "")) (defn notifications-settings [] + (let [{:keys [remote-push-notifications-enabled? + send-push-notifications? + push-notifications-block-mentions? + push-notifications-server-enabled? + push-notifications-from-contacts-only?]} + @(re-frame/subscribe [:multiaccount])] + [react/view {:flex 1} + [topbar/topbar {:title :t/notification-settings}] + [react/scroll-view {:style {:flex 1} + :content-container-style {:padding-vertical 8}} + [quo/list-item + {:size :small + :title (i18n/label :t/notifications) + :accessibility-label :notifications-button + :active remote-push-notifications-enabled? + :on-press #(re-frame/dispatch [::notifications/switch (not remote-push-notifications-enabled?)]) + :accessory :switch}] + [react/view {:height 1 + :background-color (:ui-02 @quo-colors/theme) + :margin-vertical 8}] + [quo/list-header (i18n/label :t/notifications-preferences)] + [quo/list-item + {:size :small + :title (i18n/label :t/notifications-non-contacts) + :accessibility-label :notifications-button + :active (and remote-push-notifications-enabled? + (not push-notifications-from-contacts-only?)) + :on-press #(re-frame/dispatch + [::notifications/switch-non-contacts (not push-notifications-from-contacts-only?)]) + :accessory :switch}] + [quo/list-item + {:size :small + :title (i18n/label :t/allow-mention-notifications) + :accessibility-label :notifications-button + :active (and remote-push-notifications-enabled? + (not push-notifications-block-mentions?)) + :on-press #(re-frame/dispatch + [::notifications/switch-block-mentions (not push-notifications-block-mentions?)]) + :accessory :switch}] + [quo/list-item + {:size :small + :title (i18n/label :t/send-push-notifications) + :accessibility-label :send-push-notifications-button + :active send-push-notifications? + :on-press #(re-frame/dispatch + [::notifications/switch-send-push-notifications (not send-push-notifications?)]) + :accessory :switch}] + [quo/list-item + {:size :small + :title (i18n/label :t/push-notifications-server-enabled) + :accessibility-label :send-push-notifications-button + :active (and remote-push-notifications-enabled? + push-notifications-server-enabled?) + :on-press #(re-frame/dispatch + [::notifications/switch-push-notifications-server-enabled (not push-notifications-server-enabled?)]) + :accessory :switch}] + [quo/list-item + {:size :small + :title (i18n/label :t/push-notifications-servers) + :accessibility-label :send-push-notifications-button + :chevron true + :on-press #(re-frame/dispatch + [:navigate-to :notifications-servers])}]]])) + +(defn notifications-onboarding [] [react/view {:flex 1 :background-color colors/white :align-items :center :padding-bottom 16} [react/text {:style {:margin-top 72 :margin-bottom 16 @@ -19,7 +91,7 @@ :style {:width 118 :height 118}}]] [quo/button {:on-press #(do (re-frame/dispatch - [:multiaccounts.ui/notifications-switched true]) + [::notifications/switch true]) (re-frame/dispatch [:navigate-to :welcome])) :accessibility-label :enable-notifications} (i18n/label :t/intro-wizard-title6)] @@ -27,3 +99,40 @@ :accessibility-label :maybe-later :on-press #(re-frame/dispatch [:navigate-to :welcome])} (i18n/label :t/maybe-later)]]) + +(defn server-view [{:keys [public-key type registered]}] + [quo/list-item + {:size :small + :title (str (subs public-key 0 8) + " " + (if (= type notifications/server-type-custom) + (i18n/label :t/custom) + (i18n/label :t/default)) + " " + (if registered + (i18n/label :t/registered) + (i18n/label :t/not-registered)))}]) + +(defview notifications-servers [] + (letsubs [servers [:push-notifications/servers]] + {:component-did-mount #(re-frame/dispatch [::notifications/fetch-servers])} + [react/view {:flex 1} + [topbar/topbar {:title :t/notification-servers}] + [react/scroll-view {:style {:flex 1} + :content-container-style {:padding-vertical 8}} + (map server-view servers) + [react/keyboard-avoiding-view {} + [react/view {:style {:padding-horizontal 20}} + [quo/text-input + {:label (i18n/label :t/server) + :placeholder (i18n/label :t/specify-server-public-key) + :value @server + :on-change-text #(reset! server %) + :auto-focus true}]] + [quo/button {:type :secondary + :after :main-icon/next + :disabled (empty? @server) + :on-press #(do + (re-frame/dispatch [::notifications/add-server @server]) + (reset! server ""))} + (i18n/label :t/save)]]]])) diff --git a/src/status_im/ui/screens/profile/contact/views.cljs b/src/status_im/ui/screens/profile/contact/views.cljs index c84cbaf835..2c508a93bf 100644 --- a/src/status_im/ui/screens/profile/contact/views.cljs +++ b/src/status_im/ui/screens/profile/contact/views.cljs @@ -2,6 +2,7 @@ (:require [quo.core :as quo] [re-frame.core :as re-frame] [status-im.i18n :as i18n] + [status-im.chat.models :as chat.models] [status-im.multiaccounts.core :as multiaccounts] [status-im.ui.components.chat-icon.screen :as chat-icon] [status-im.ui.components.icons.vector-icons :as icons] @@ -14,6 +15,7 @@ [status-im.ui.components.colors :as colors] [status-im.ui.components.toolbar :as toolbar] [status-im.ui.components.keyboard-avoid-presentation :as kb-presentation] + [status-im.utils.platform :as platform] [reagent.core :as reagent] [clojure.string :as string]) (:require-macros [status-im.utils.views :as views])) @@ -76,15 +78,22 @@ (i18n/label :t/profile-details)]] [render-detail contact]])) -(defn render-chat-settings [{:keys [names]}] - [quo/list-item - {:title (i18n/label :t/nickname) - :size :small - :accessibility-label :profile-nickname-item - :accessory :text - :accessory-text (or (:nickname names) (i18n/label :t/none)) - :on-press #(re-frame/dispatch [:navigate-to :nickname]) - :chevron true}]) +(defn render-chat-settings [{:keys [public-key names]}] + (let [muted? (:muted @(re-frame/subscribe [:chats/chat public-key]))] + [quo/list-item + {:title (i18n/label :t/nickname) + :size :small + :accessibility-label :profile-nickname-item + :accessory :text + :accessory-text (or (:nickname names) (i18n/label :t/none)) + :on-press #(re-frame/dispatch [:navigate-to :nickname]) + :chevron true}] + [quo/list-item + {:title (i18n/label :mute-chat) + :active muted? + :accessibility-label :mute-chat + :on-press #(re-frame/dispatch [::chat.models/mute-chat-toggled public-key (not muted?)]) + :accessory :switch}])) (defn chat-settings [contact] [react/view @@ -195,5 +204,8 @@ :on-press action}]))] [react/view styles/contact-profile-details-container [profile-details contact] - [chat-settings contact]] + ;; Mute chat is only supported on ios for now + (when platform/ios? + [react/view {} + [chat-settings contact]])] [block-contact-action contact]]])))) diff --git a/src/status_im/ui/screens/profile/user/views.cljs b/src/status_im/ui/screens/profile/user/views.cljs index 3ad71f6614..a9c037edf1 100644 --- a/src/status_im/ui/screens/profile/user/views.cljs +++ b/src/status_im/ui/screens/profile/user/views.cljs @@ -3,6 +3,7 @@ [reagent.core :as reagent] [status-im.i18n :as i18n] [quo.core :as quo] + [status-im.notifications.core :as notifications] [status-im.ui.components.colors :as colors] [status-im.multiaccounts.core :as multiaccounts] [status-im.ui.components.common.common :as components.common] @@ -65,8 +66,8 @@ (defn content [] (let [{:keys [preferred-name mnemonic - keycard-pairing - notifications-enabled?]} + notifications-enabled? + keycard-pairing]} @(re-frame/subscribe [:multiaccount]) active-contacts-count @(re-frame/subscribe [:contacts/active-count]) tribute-to-talk @(re-frame/subscribe [:tribute-to-talk/profile]) @@ -126,16 +127,23 @@ :accessibility-label :appearance-settings-button :chevron true :on-press #(re-frame/dispatch [:navigate-to :appearance])}] - (when (and platform/android? - config/local-notifications?) + (if platform/ios? [quo/list-item {:icon :main-icons/notification :title (i18n/label :t/notifications) - :accessibility-label :notifications-button - :active notifications-enabled? - :on-press #(re-frame/dispatch - [:multiaccounts.ui/notifications-switched (not notifications-enabled?)]) - :accessory :switch}]) + :accessibility-label :notifications-settings-button + :chevron true + :on-press #(re-frame/dispatch [:navigate-to :notifications])}] + (when (and platform/android? + config/local-notifications?) + [quo/list-item + {:icon :main-icons/notification + :title (i18n/label :t/notifications) + :accessibility-label :notifications-settings-button + :active notifications-enabled? + :on-press #(re-frame/dispatch + [::notifications/switch (not notifications-enabled?)]) + :accessory :switch}])) [quo/list-item {:icon :main-icons/mobile :title (i18n/label :t/sync-settings) diff --git a/src/status_im/ui/screens/routing/main.cljs b/src/status_im/ui/screens/routing/main.cljs index 341021b190..872578f33a 100644 --- a/src/status_im/ui/screens/routing/main.cljs +++ b/src/status_im/ui/screens/routing/main.cljs @@ -23,8 +23,8 @@ [quo.previews.main :as quo.preview] [status-im.utils.config :as config] [status-im.ui.screens.chat.image.preview.views :as image-preview] - [status-im.ui.screens.notifications-settings.views :as notifications-settings] - [status-im.ui.screens.profile.contact.views :as contact])) + [status-im.ui.screens.profile.contact.views :as contact] + [status-im.ui.screens.notifications-settings.views :as notifications-settings])) (defonce main-stack (navigation/create-stack)) (defonce bottom-tabs (navigation/create-bottom-tabs)) @@ -114,7 +114,12 @@ {:name :notifications-settings :back-handler :noop :insets {:bottom true} - :component notifications-settings/notifications-settings}] + :component notifications-settings/notifications-settings} + {:name :notifications-onboarding + :back-handler :noop + :insets {:bottom true} + :component notifications-settings/notifications-onboarding}] + (when config/quo-preview-enabled? [{:name :quo-preview :insets {:top false :bottom false} diff --git a/src/status_im/ui/screens/routing/profile_stack.cljs b/src/status_im/ui/screens/routing/profile_stack.cljs index 8829c55202..5a4a38e851 100644 --- a/src/status_im/ui/screens/routing/profile_stack.cljs +++ b/src/status_im/ui/screens/routing/profile_stack.cljs @@ -37,6 +37,7 @@ [status-im.ui.components.tabbar.styles :as tabbar.styles] [status-im.ui.screens.routing.core :as navigation] [status-im.ui.screens.appearance.views :as appearance] + [status-im.ui.screens.notifications-settings.views :as notifications-settings] [status-im.ui.screens.privacy-and-security-settings.delete-profile :as delete-profile])) (defonce stack (navigation/create-stack)) @@ -83,6 +84,10 @@ :component privacy-and-security/privacy-and-security} {:name :appearance :component appearance/appearance} + {:name :notifications + :component notifications-settings/notifications-settings} + {:name :notifications-servers + :component notifications-settings/notifications-servers} {:name :sync-settings :component sync-settings/sync-settings} {:name :advanced-settings diff --git a/src/status_im/utils/config.cljs b/src/status_im/utils/config.cljs index 7582d8d384..a014eadaa2 100644 --- a/src/status_im/utils/config.cljs +++ b/src/status_im/utils/config.cljs @@ -46,6 +46,7 @@ (def log-level (string/upper-case (get-config :LOG_LEVEL ""))) (def fleet (get-config :FLEET "eth.staging")) +(def apn-topic (get-config :APN_TOPIC "im.status.ethereum")) (def default-network (get-config :DEFAULT_NETWORK)) (def pow-target (js/parseFloat (get-config :POW_TARGET "0.0001"))) (def pow-time (js/parseInt (get-config :POW_TIME "1"))) diff --git a/status-go-version.json b/status-go-version.json index 400f2e205d..04fba1767f 100644 --- a/status-go-version.json +++ b/status-go-version.json @@ -2,7 +2,7 @@ "_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh ' instead", "owner": "status-im", "repo": "status-go", - "version": "v0.60.2", - "commit-sha1": "57728224d45ce3086e135988ae02e247abbc7b60", - "src-sha256": "1smgazlkgjxqq27ncgxagdi3523vcnmrca7lgj0lbxb4kbqgmmbl" + "version": "v0.61.1", + "commit-sha1": "61b345ff3395e4d031da1c4b497cc431a4ab2177", + "src-sha256": "1dg9w9fdi5isdc72ydxqgin6bg8b7jqkavjs2x8bvl9lhf2mqm3c" } diff --git a/test/appium/views/profile_view.py b/test/appium/views/profile_view.py index 8be6dd37b5..97dec3c3d8 100644 --- a/test/appium/views/profile_view.py +++ b/test/appium/views/profile_view.py @@ -461,7 +461,7 @@ class AboutButton(BaseButton): class PrifileNotificationsButton(BaseButton): def __init__(self, driver): super().__init__(driver) - self.locator = self.Locator.accessibility_id("notifications-button") + self.locator = self.Locator.accessibility_id("notifications-settings-button") class RemovePictureButton(BaseButton): diff --git a/translations/en.json b/translations/en.json index 4d6b515330..c8d228e9d4 100644 --- a/translations/en.json +++ b/translations/en.json @@ -790,6 +790,18 @@ "not-keycard-text": "The card you used is not a Keycard. You need to purchase a Keycard to use it", "not-keycard-title": "Not a Keycard", "notifications": "Notifications", + "notifications-settings": "Notifications", + "notification-settings": "Notification settings", + "notifications-servers": "Notification servers", + "notifications-preferences": "Notification preferences", + "notifications-switch": "Show notifications", + "notifications-non-contacts": "Notifications from non-contacts", + "send-push-notifications": "Send push notifications", + "push-notifications-server-enabled": "Server enabled", + "push-notifications-servers": "Push notification servers", + "allow-mention-notifications": "Show @ mentions", + "server": "Server", + "specify-server-public-key": "Enter server public key", "notify": "Notify", "off": "Off", "offline": "Offline", @@ -960,6 +972,7 @@ "sharing-share": "Share", "show-less": "Show less", "show-more": "Show more", + "show-notifications": "Show notifications", "show-qr": "Show QR code", "show-transaction-data": "Show transaction data", "sign-and-send": "Sign and send", @@ -1220,6 +1233,8 @@ "private-notifications-descr": "Status will notify you about new messages. You can edit your notification preferences later in settings.", "maybe-later": "Maybe later", "join": "Join", + "registered": "registered", + "not-registered": "not registered", "audio-recorder-error": "Recorder error", "audio-recorder": "Recorder", "audio-recorder-max-ms-reached": "Maximum recording time reached", diff --git a/yarn.lock b/yarn.lock index a3741e9250..061bc4f0b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1344,6 +1344,13 @@ resolved "https://registry.yarnpkg.com/@react-native-community/netinfo/-/netinfo-4.7.0.tgz#7482d36836cac69d0a0ae25581f65bc472639930" integrity sha512-a/sDB+AsLEUNmhAUlAaTYeXKyQdFGBUfatqKkX5jluBo2CB3OAuTHfm7rSjcaLB9EmG5iSq3fOTpync2E7EYTA== +"@react-native-community/push-notification-ios@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@react-native-community/push-notification-ios/-/push-notification-ios-1.4.1.tgz#02b46fb793926f34aa275605ed49f03015e893b3" + integrity sha512-Y+4LS10R+yc17wu54tlDcxgW/SugEAz2dNjmil9I7KUtaZIOc0hTvAE8dUvYTEDvYQ9uYrXI+OqdElTE3FJ3FA== + dependencies: + invariant "^2.2.4" + "@react-native-community/slider@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@react-native-community/slider/-/slider-3.0.0.tgz#ffbf78689fc0572fb5c1e2ccb61b2ef074d3dcd2"