Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Andrey Shovkoplyas 2020-06-12 10:54:28 +02:00 committed by Andrea Maria Piana
parent f9df0f367f
commit 0675d0d8d7
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
34 changed files with 550 additions and 83 deletions

1
.env
View File

@ -24,3 +24,4 @@ QR_READ_TEST_MENU=1
ENABLE_ROOT_ALERT=1 ENABLE_ROOT_ALERT=1
ENABLE_REFERRAL_INVITE=1 ENABLE_REFERRAL_INVITE=1
ENABLE_QUO_PREVIEW=1 ENABLE_QUO_PREVIEW=1
APN_TOPIC=im.status.ethereum.pr

View File

@ -23,3 +23,4 @@ KEYCARD_TEST_MENU=1
QR_READ_TEST_MENU=1 QR_READ_TEST_MENU=1
ENABLE_ROOT_ALERT=0 ENABLE_ROOT_ALERT=0
ENABLE_REFERRAL_INVITE=1 ENABLE_REFERRAL_INVITE=1
APN_TOPIC=im.status.ethereum.pr

View File

@ -22,3 +22,4 @@ KEYCARD_TEST_MENU=0
ENABLE_ROOT_ALERT=1 ENABLE_ROOT_ALERT=1
ENABLE_REFERRAL_INVITE=1 ENABLE_REFERRAL_INVITE=1
DISABLE_WALLET_ON_MOBILE_NETWORK=1 DISABLE_WALLET_ON_MOBILE_NETWORK=1
APN_TOPIC=im.status.ethereum.pr

View File

@ -328,6 +328,8 @@ PODS:
- React - React
- RNCMaskedView (0.1.9): - RNCMaskedView (0.1.9):
- React - React
- RNCPushNotificationIOS (1.4.1):
- React
- RNDeviceInfo (5.6.1): - RNDeviceInfo (5.6.1):
- React - React
- RNFS (2.16.6): - RNFS (2.16.6):
@ -363,7 +365,7 @@ PODS:
- SQLCipher/standard (3.4.2): - SQLCipher/standard (3.4.2):
- SQLCipher/common - SQLCipher/common
- SSZipArchive (2.2.3) - SSZipArchive (2.2.3)
- TOCropViewController (2.5.3) - TOCropViewController (2.5.4)
- TouchID (4.4.1): - TouchID (4.4.1):
- React - React
- Yoga (1.14.0) - Yoga (1.14.0)
@ -435,6 +437,7 @@ DEPENDENCIES:
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)" - "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)" - "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)"
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)" - "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`) - RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNFS (from `../node_modules/react-native-fs`) - RNFS (from `../node_modules/react-native-fs`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
@ -554,6 +557,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/@react-native-community/clipboard" :path: "../node_modules/@react-native-community/clipboard"
RNCMaskedView: RNCMaskedView:
:path: "../node_modules/@react-native-community/masked-view" :path: "../node_modules/@react-native-community/masked-view"
RNCPushNotificationIOS:
:path: "../node_modules/@react-native-community/push-notification-ios"
RNDeviceInfo: RNDeviceInfo:
:path: "../node_modules/react-native-device-info" :path: "../node_modules/react-native-device-info"
RNFS: RNFS:
@ -596,7 +601,7 @@ SPEC CHECKSUMS:
Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7 Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7
FlipperKit: afd4259ef9eadeeb2d30250b37d95cb3b6b97a69 FlipperKit: afd4259ef9eadeeb2d30250b37d95cb3b6b97a69
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51 Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 682164e7ac67e41afd8f7b6a37a96d04caf61cc0 glog: 1f3da668190260b06b429bb211bfbee5cd790c28
OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355 OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355
Permission-Camera: afad27bf90337684d4a86f3825112d648c8c4d3b Permission-Camera: afad27bf90337684d4a86f3825112d648c8c4d3b
Permission-Microphone: 0ffabc3fe1c75cfb260525ee3f529383c9f4368c Permission-Microphone: 0ffabc3fe1c75cfb260525ee3f529383c9f4368c
@ -635,6 +640,7 @@ SPEC CHECKSUMS:
RNCAsyncStorage: d059c3ee71738c39834a627476322a5a8cd5bf36 RNCAsyncStorage: d059c3ee71738c39834a627476322a5a8cd5bf36
RNCClipboard: 8148e21ac347c51fd6cd4b683389094c216bb543 RNCClipboard: 8148e21ac347c51fd6cd4b683389094c216bb543
RNCMaskedView: 71fc32d971f03b7f03d6ab6b86b730c4ee64f5b6 RNCMaskedView: 71fc32d971f03b7f03d6ab6b86b730c4ee64f5b6
RNCPushNotificationIOS: c145c6253ea016e5efeff604f2720736b4a596f7
RNDeviceInfo: b6e650fbd234732c759544218657d549b4339038 RNDeviceInfo: b6e650fbd234732c759544218657d549b4339038
RNFS: 2bd9eb49dc82fa9676382f0585b992c424cd59df RNFS: 2bd9eb49dc82fa9676382f0585b992c424cd59df
RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38 RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38
@ -648,11 +654,11 @@ SPEC CHECKSUMS:
RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f
SQLCipher: f9fcf29b2e59ced7defc2a2bdd0ebe79b40d4990 SQLCipher: f9fcf29b2e59ced7defc2a2bdd0ebe79b40d4990
SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9 SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9
TOCropViewController: 20a14b6a7a098308bf369e7c8d700dc983a974e6 TOCropViewController: 2a1ae1242600b1f2d996fd91a5268b2309a33b5c
TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4 TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4
Yoga: 3ebccbdd559724312790e7742142d062476b698e Yoga: 3ebccbdd559724312790e7742142d062476b698e
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: 5faa578ff5cb7a30abc18b9d620df288750a72fe PODFILE CHECKSUM: 5faa578ff5cb7a30abc18b9d620df288750a72fe
COCOAPODS: 1.9.1 COCOAPODS: 1.9.3

View File

@ -9,8 +9,9 @@
#import <React/RCTBridgeDelegate.h> #import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <UserNotifications/UNUserNotificationCenter.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate> @interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>
@property (nonatomic, strong) UIWindow *window; @property (nonatomic, strong) UIWindow *window;

View File

@ -20,6 +20,9 @@
#import <React/RCTBundleURLProvider.h> #import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h> #import <React/RCTRootView.h>
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
#if DEBUG #if DEBUG
#import <FlipperKit/FlipperClient.h> #import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h> #import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
@ -88,6 +91,9 @@ static void InitializeFlipper(UIApplication *application) {
[self.window makeKeyAndVisible]; [self.window makeKeyAndVisible];
[RNSplashScreen show]; [RNSplashScreen show];
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
return YES; 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 @end

View File

@ -17,6 +17,7 @@
"@react-native-community/hooks": "^2.5.1", "@react-native-community/hooks": "^2.5.1",
"@react-native-community/masked-view": "^0.1.6", "@react-native-community/masked-view": "^0.1.6",
"@react-native-community/netinfo": "^4.4.0", "@react-native-community/netinfo": "^4.4.0",
"@react-native-community/push-notification-ios": "^1.4.1",
"@react-native-community/slider": "^3.0.0", "@react-native-community/slider": "^3.0.0",
"@react-navigation/bottom-tabs": "^5.7.0", "@react-navigation/bottom-tabs": "^5.7.0",
"@react-navigation/native": "^5.7.0", "@react-navigation/native": "^5.7.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

View File

@ -190,6 +190,7 @@
#js {:localNotification identity #js {:localNotification identity
:requestPermission identity}) :requestPermission identity})
(def push-notification-ios #js {})
;; Update i18n_resources.cljs ;; Update i18n_resources.cljs
(defn mock [module] (defn mock [module]
(case module (case module
@ -219,6 +220,7 @@
"react-native-haptic-feedback" react-native-haptic-feedback "react-native-haptic-feedback" react-native-haptic-feedback
"react-native-device-info" react-native-device-info "react-native-device-info" react-native-device-info
"react-native-push-notification" react-native-push-notification "react-native-push-notification" react-native-push-notification
"@react-native-community/push-notification-ios" push-notification-ios
"./fleets.js" default-fleets "./fleets.js" default-fleets
"./chats.js" default-chats "./chats.js" default-chats
"../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json")) "../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json"))

View File

@ -1,5 +1,6 @@
(ns status-im.chat.models (ns status-im.chat.models
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[taoensso.timbre :as log]
[status-im.multiaccounts.model :as multiaccounts.model] [status-im.multiaccounts.model :as multiaccounts.model]
[status-im.transport.filters.core :as transport.filters] [status-im.transport.filters.core :as transport.filters]
[status-im.contact.core :as contact.core] [status-im.contact.core :as contact.core]
@ -136,15 +137,15 @@
(fx/defn upsert-chat (fx/defn upsert-chat
"Upsert chat when not deleted" "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 (fx/merge cofx
(ensure-chat chat-props) (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 (fx/defn handle-save-chat
{:events [::save-chat]} {:events [::save-chat]}
[{:keys [db] :as cofx} chat-id] [{:keys [db] :as cofx} chat-id on-success]
(chats-store/save-chat cofx (get-in db [:chats chat-id]))) (chats-store/save-chat cofx (get-in db [:chats chat-id]) on-success))
(fx/defn handle-mark-all-read-successful (fx/defn handle-mark-all-read-successful
{:events [::mark-all-read-successful]} {:events [::mark-all-read-successful]}
@ -172,7 +173,8 @@
:public? true :public? true
:might-have-join-time-messages? true :might-have-join-time-messages? true
:unviewed-messages-count 0 :unviewed-messages-count 0
:loaded-unviewed-messages-ids #{}})) :loaded-unviewed-messages-ids #{}}
nil))
(fx/defn clear-history (fx/defn clear-history
"Clears history of the particular chat" "Clears history of the particular chat"
@ -192,7 +194,7 @@
:unviewed-messages-count 0 :unviewed-messages-count 0
:deleted-at-clock-value last-message-clock-value}))} :deleted-at-clock-value last-message-clock-value}))}
(messages-store/delete-messages-by-chat-id chat-id) (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 (fx/defn deactivate-chat
"Deactivate chat in db, no side effects" "Deactivate chat in db, no side effects"
@ -253,7 +255,8 @@
(when (not= (multiaccounts.model/current-public-key cofx) chat-id) (when (not= (multiaccounts.model/current-public-key cofx) chat-id)
(fx/merge cofx (fx/merge cofx
(upsert-chat {:chat-id chat-id (upsert-chat {:chat-id chat-id
:is-active true}) :is-active true}
nil)
(transport.filters/load-chat chat-id) (transport.filters/load-chat chat-id)
(navigate-to-chat chat-id)))) (navigate-to-chat chat-id))))
@ -293,6 +296,29 @@
{:db (assoc db :contacts/identity identity)} {:db (assoc db :contacts/identity identity)}
(navigation/navigate-to-cofx :profile nil))))) (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 (fx/defn show-profile
{:events [:chat.ui/show-profile]} {:events [:chat.ui/show-profile]}
[cofx identity] [cofx identity]

View File

@ -15,7 +15,7 @@
cofx {:now "now" cofx {:now "now"
:db {:contacts/contacts {chat-id :db {:contacts/contacts {chat-id
{:name contact-name}}}} {: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])] actual-chat (get-in response [:db :chats chat-id])]
(testing "it adds the chat to the chats collection" (testing "it adds the chat to the chats collection"
(is actual-chat)) (is actual-chat))
@ -36,7 +36,7 @@
:extra-prop "some"} :extra-prop "some"}
cofx {:db {:chats {chat-id {:is-active true cofx {:db {:chats {chat-id {:is-active true
:name "old-name"}}}} :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])] actual-chat (get-in response [:db :chats chat-id])]
(testing "it adds the chat to the chats collection" (testing "it adds the chat to the chats collection"
(is actual-chat)) (is actual-chat))

View File

@ -94,10 +94,12 @@
(update :last-message #(when % (messages/<-rpc %))) (update :last-message #(when % (messages/<-rpc %)))
(dissoc :chatType :members))) (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") {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "saveChat")
:params [(->rpc chat)] :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 %)}]}) :on-failure #(log/error "failed to save chat" chat-id %)}]})
(fx/defn fetch-chats-rpc [cofx {:keys [on-success]}] (fx/defn fetch-chats-rpc [cofx {:keys [on-success]}]

View File

@ -71,6 +71,8 @@
"shhext_updateMessageOutgoingStatus" {} "shhext_updateMessageOutgoingStatus" {}
"shhext_chatMessages" {} "shhext_chatMessages" {}
"shhext_saveChat" {} "shhext_saveChat" {}
"shhext_muteChat" {}
"shhext_unmuteChat" {}
"shhext_contacts" {} "shhext_contacts" {}
"shhext_prepareContent" {} "shhext_prepareContent" {}
"shhext_blockContact" {} "shhext_blockContact" {}
@ -93,6 +95,18 @@
"shhext_sendGroupChatInvitationRequest" {} "shhext_sendGroupChatInvitationRequest" {}
"shhext_sendGroupChatInvitationRejection" {} "shhext_sendGroupChatInvitationRejection" {}
"shhext_getGroupChatInvitations" {} "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_post" {}
"wakuext_startMessenger" {} "wakuext_startMessenger" {}
"wakuext_sendPairInstallation" {} "wakuext_sendPairInstallation" {}
@ -130,6 +144,8 @@
"wakuext_updateMessageOutgoingStatus" {} "wakuext_updateMessageOutgoingStatus" {}
"wakuext_chatMessages" {} "wakuext_chatMessages" {}
"wakuext_saveChat" {} "wakuext_saveChat" {}
"wakuext_muteChat" {}
"wakuext_unmuteChat" {}
"wakuext_contacts" {} "wakuext_contacts" {}
"wakuext_prepareContent" {} "wakuext_prepareContent" {}
"wakuext_blockContact" {} "wakuext_blockContact" {}
@ -152,6 +168,18 @@
"wakuext_sendGroupChatInvitationRequest" {} "wakuext_sendGroupChatInvitationRequest" {}
"wakuext_sendGroupChatInvitationRejection" {} "wakuext_sendGroupChatInvitationRejection" {}
"wakuext_getGroupChatInvitations" {} "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" {} "status_chats" {}
"wallet_getTransfers" {} "wallet_getTransfers" {}
"wallet_getTokensBalances" {} "wallet_getTokensBalances" {}
@ -210,16 +238,20 @@
(str "shhext_" method))) (str "shhext_" method)))
(defn call (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)] (if-let [method-options (json-rpc-api method)]
(let [params (or params []) (let [params (or params [])
{:keys [id on-result subscription?] {:keys [id on-result subscription?]
:or {on-result identity :or {on-result identity
id 1}} method-options id 1}} method-options
on-error (or (on-error-retry call arg) on-error (or
#(log/warn :json-rpc/error method :error % :params params))] on-error
(on-error-retry call arg)
#(log/warn :json-rpc/error method :error % :params params))]
(if (nil? method) (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 (status/call-private-rpc
(types/clj->json {:jsonrpc "2.0" (types/clj->json {:jsonrpc "2.0"
:id id :id id

View File

@ -117,7 +117,8 @@
(fx/merge cofx (fx/merge cofx
(models.chat/deactivate-chat chat-id) (models.chat/deactivate-chat chat-id)
(models.chat/upsert-chat {:chat-id chat-id (models.chat/upsert-chat {:chat-id chat-id
:is-active false}) :is-active false}
nil)
(navigation/navigate-to-cofx :home {}))) (navigation/navigate-to-cofx :home {})))
(defn- valid-name? [name] (defn- valid-name? [name]
@ -167,4 +168,4 @@
{:db (update db :group-chat/invitations #(reduce (fn [acc {:keys [id] :as inv}] {:db (update db :group-chat/invitations #(reduce (fn [acc {:keys [id] :as inv}]
(assoc acc id inv)) (assoc acc id inv))
% %
invitations))}) invitations))})

View File

@ -3,7 +3,6 @@
[status-im.ethereum.stateofus :as stateofus] [status-im.ethereum.stateofus :as stateofus]
[status-im.multiaccounts.update.core :as multiaccounts.update] [status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.native-module.core :as native-module] [status-im.native-module.core :as native-module]
[status-im.notifications.core :as notifications]
[status-im.utils.fx :as fx] [status-im.utils.fx :as fx]
[status-im.utils.gfycat.core :as gfycat] [status-im.utils.gfycat.core :as gfycat]
[status-im.utils.identicon :as identicon] [status-im.utils.identicon :as identicon]
@ -87,17 +86,6 @@
:dev-mode? dev-mode? :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 (fx/defn switch-chaos-mode
[{:keys [db] :as cofx} chaos-mode?] [{:keys [db] :as cofx} chaos-mode?]
(when (:multiaccount db) (when (:multiaccount db)

View File

@ -138,8 +138,7 @@
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(fx/merge cofx (fx/merge cofx
{:db (dissoc db :intro-wizard)} {:db (dissoc db :intro-wizard)}
(navigation/navigate-to-cofx (if platform/android? (navigation/navigate-to-cofx :notifications-onboarding nil)))
:notifications-settings :welcome) nil)))
(fx/defn init-key-generation (fx/defn init-key-generation
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
@ -252,6 +251,7 @@
:dapps-address (:address wallet-account) :dapps-address (:address wallet-account)
:latest-derived-path 0 :latest-derived-path 0
:signing-phrase signing-phrase :signing-phrase signing-phrase
:send-push-notifications? true
:installation-id (random-guid-generator)} :installation-id (random-guid-generator)}
constants/default-multiaccount) constants/default-multiaccount)
;; The address from which we derive any chat ;; The address from which we derive any chat

View File

@ -22,7 +22,6 @@
[status-im.utils.identicon :as identicon] [status-im.utils.identicon :as identicon]
[status-im.utils.keychain.core :as keychain] [status-im.utils.keychain.core :as keychain]
[status-im.utils.logging.core :as logging] [status-im.utils.logging.core :as logging]
[status-im.utils.platform :as platform]
[status-im.utils.security :as security] [status-im.utils.security :as security]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
@ -88,8 +87,7 @@
{:db (update db :keycard dissoc :flow)} {:db (update db :keycard dissoc :flow)}
(if (= :import flow) (if (= :import flow)
(navigation/navigate-to-cofx :intro-stack {:screen :keycard-recovery-success}) (navigation/navigate-to-cofx :intro-stack {:screen :keycard-recovery-success})
(navigation/navigate-to-cofx (if platform/android? (navigation/navigate-to-cofx :notifications-onboarding nil))))))
:notifications-settings :welcome) nil))))))
(fx/defn initialize-dapp-permissions (fx/defn initialize-dapp-permissions
{:events [::initialize-dapp-permissions]} {:events [::initialize-dapp-permissions]}
@ -192,8 +190,7 @@
(fn [accounts custom-tokens] (fn [accounts custom-tokens]
(re-frame/dispatch [::initialize-wallet (re-frame/dispatch [::initialize-wallet
accounts custom-tokens]))} accounts custom-tokens]))}
(and platform/android? notifications-enabled?
notifications-enabled?)
(assoc ::notifications/enable nil)) (assoc ::notifications/enable nil))
(acquisition/login) (acquisition/login)
(initialize-appearance) (initialize-appearance)

View File

@ -6,7 +6,8 @@
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.transport.core :as transport] [status-im.transport.core :as transport]
[status-im.utils.fx :as fx] [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 (fx/defn logout-method
[{:keys [db] :as cofx} {:keys [auth-method logout?]}] [{:keys [db] :as cofx} {:keys [auth-method logout?]}]
@ -15,6 +16,7 @@
{::logout nil {::logout nil
:keychain/clear-user-password key-uid :keychain/clear-user-password key-uid
::init/open-multiaccounts #(re-frame/dispatch [::init/initialize-multiaccounts % {:logout? logout?}])} ::init/open-multiaccounts #(re-frame/dispatch [::init/initialize-multiaccounts % {:logout? logout?}])}
(notifications/logout-disable)
(keychain/save-auth-method key-uid auth-method) (keychain/save-auth-method key-uid auth-method)
(transport/stop-whisper) (transport/stop-whisper)
(chaos-mode/stop-checking) (chaos-mode/stop-checking)

View File

@ -39,3 +39,10 @@
(multiaccount-update cofx (multiaccount-update cofx
:mnemonic nil :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))}))

View File

@ -2,7 +2,48 @@
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.utils.fx :as fx] [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 ;; FIXME: Repalce with request permission from audio messages PR lib
(re-frame/reg-fx (re-frame/reg-fx
@ -23,9 +64,164 @@
(re-frame/reg-fx (re-frame/reg-fx
::enable ::enable
(fn [_] (fn [_]
(status/enable-notifications))) (if platform/android?
(status/enable-notifications)
(enable-ios-notifications))))
(re-frame/reg-fx (re-frame/reg-fx
::disable ::disable
(fn [_] (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 %]))}]})

View File

@ -197,6 +197,9 @@
;; delete profile ;; delete profile
(reg-root-key-sub :delete-profile/error :delete-profile/error) (reg-root-key-sub :delete-profile/error :delete-profile/error)
;; push notifications
(reg-root-key-sub :push-notifications/servers :push-notifications/servers)
;;GENERAL ============================================================================================================== ;;GENERAL ==============================================================================================================
(re-frame/reg-sub (re-frame/reg-sub

View File

@ -132,4 +132,4 @@
[react/i18n-text {:style styles/profile-icon-edit-text :key :edit}]]) [react/i18n-text {:style styles/profile-icon-edit-text :key :edit}]])
(if (and photo-path (seq photo-path)) (if (and photo-path (seq photo-path))
[photos/photo photo-path styles] [photos/photo photo-path styles]
[default-chat-icon name styles])])) [default-chat-icon name styles])]))

View File

@ -124,7 +124,7 @@
:accessibility-label :unviewed-messages-public}] :accessibility-label :unviewed-messages-public}]
[badge/message-counter unviewed-messages-count])])) [badge/message-counter unviewed-messages-count])]))
(defn icon-style [] (def icon-style
{:color colors/black {:color colors/black
:width 15 :width 15
:height 15 :height 15
@ -134,7 +134,7 @@
(defn home-list-item [home-item] (defn home-list-item [home-item]
(let [{:keys [chat-id chat-name color online group-chat (let [{:keys [chat-id chat-name color online group-chat
public? timestamp last-message]} public? timestamp last-message muted]}
home-item home-item
private-group? (and group-chat (not public?)) private-group? (and group-chat (not public?))
public-group? (and group-chat public?)] public-group? (and group-chat public?)]
@ -148,13 +148,16 @@
:padding-right 16 :padding-right 16
:align-items :center} :align-items :center}
(cond (cond
muted
[icons/icon :main-icons/tiny-muted (assoc icon-style :color colors/gray)]
private-group? private-group?
[icons/icon :main-icons/tiny-group (icon-style)] [icons/icon :main-icons/tiny-group icon-style]
public-group? public-group?
[icons/icon :main-icons/tiny-public (icon-style)] [icons/icon :main-icons/tiny-public icon-style]
:else :else
[icons/icon :main-icons/tiny-new-contact (icon-style)]) [icons/icon :main-icons/tiny-new-contact icon-style])
[quo/text {:weight :medium [quo/text {:weight :medium
:color (when muted :secondary)
:accessibility-label :chat-name-text :accessibility-label :chat-name-text
:ellipsize-mode :tail :ellipsize-mode :tail
:number-of-lines 1} :number-of-lines 1}

View File

@ -1,12 +1,84 @@
(ns status-im.ui.screens.notifications-settings.views (ns status-im.ui.screens.notifications-settings.views
(:require [status-im.ui.components.colors :as colors] (:require-macros [status-im.utils.views :refer [defview letsubs]])
[status-im.ui.components.react :as react] (:require [re-frame.core :as re-frame]
[status-im.react-native.resources :as resources] [reagent.core :as reagent]
[status-im.i18n :as i18n]
[quo.core :as quo] [quo.core :as quo]
[re-frame.core :as re-frame] [quo.design-system.colors :as quo-colors]
[status-im.i18n :as i18n])) [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 [] (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 [react/view {:flex 1 :background-color colors/white
:align-items :center :padding-bottom 16} :align-items :center :padding-bottom 16}
[react/text {:style {:margin-top 72 :margin-bottom 16 [react/text {:style {:margin-top 72 :margin-bottom 16
@ -19,7 +91,7 @@
:style {:width 118 :style {:width 118
:height 118}}]] :height 118}}]]
[quo/button {:on-press #(do (re-frame/dispatch [quo/button {:on-press #(do (re-frame/dispatch
[:multiaccounts.ui/notifications-switched true]) [::notifications/switch true])
(re-frame/dispatch [:navigate-to :welcome])) (re-frame/dispatch [:navigate-to :welcome]))
:accessibility-label :enable-notifications} :accessibility-label :enable-notifications}
(i18n/label :t/intro-wizard-title6)] (i18n/label :t/intro-wizard-title6)]
@ -27,3 +99,40 @@
:accessibility-label :maybe-later :accessibility-label :maybe-later
:on-press #(re-frame/dispatch [:navigate-to :welcome])} :on-press #(re-frame/dispatch [:navigate-to :welcome])}
(i18n/label :t/maybe-later)]]) (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)]]]]))

View File

@ -2,6 +2,7 @@
(:require [quo.core :as quo] (:require [quo.core :as quo]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.chat.models :as chat.models]
[status-im.multiaccounts.core :as multiaccounts] [status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.chat-icon.screen :as chat-icon] [status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.icons.vector-icons :as icons] [status-im.ui.components.icons.vector-icons :as icons]
@ -14,6 +15,7 @@
[status-im.ui.components.colors :as colors] [status-im.ui.components.colors :as colors]
[status-im.ui.components.toolbar :as toolbar] [status-im.ui.components.toolbar :as toolbar]
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation] [status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
[status-im.utils.platform :as platform]
[reagent.core :as reagent] [reagent.core :as reagent]
[clojure.string :as string]) [clojure.string :as string])
(:require-macros [status-im.utils.views :as views])) (:require-macros [status-im.utils.views :as views]))
@ -76,15 +78,22 @@
(i18n/label :t/profile-details)]] (i18n/label :t/profile-details)]]
[render-detail contact]])) [render-detail contact]]))
(defn render-chat-settings [{:keys [names]}] (defn render-chat-settings [{:keys [public-key names]}]
[quo/list-item (let [muted? (:muted @(re-frame/subscribe [:chats/chat public-key]))]
{:title (i18n/label :t/nickname) [quo/list-item
:size :small {:title (i18n/label :t/nickname)
:accessibility-label :profile-nickname-item :size :small
:accessory :text :accessibility-label :profile-nickname-item
:accessory-text (or (:nickname names) (i18n/label :t/none)) :accessory :text
:on-press #(re-frame/dispatch [:navigate-to :nickname]) :accessory-text (or (:nickname names) (i18n/label :t/none))
:chevron true}]) :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] (defn chat-settings [contact]
[react/view [react/view
@ -195,5 +204,8 @@
:on-press action}]))] :on-press action}]))]
[react/view styles/contact-profile-details-container [react/view styles/contact-profile-details-container
[profile-details contact] [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]]])))) [block-contact-action contact]]]))))

View File

@ -3,6 +3,7 @@
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[quo.core :as quo] [quo.core :as quo]
[status-im.notifications.core :as notifications]
[status-im.ui.components.colors :as colors] [status-im.ui.components.colors :as colors]
[status-im.multiaccounts.core :as multiaccounts] [status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.common.common :as components.common] [status-im.ui.components.common.common :as components.common]
@ -65,8 +66,8 @@
(defn content [] (defn content []
(let [{:keys [preferred-name (let [{:keys [preferred-name
mnemonic mnemonic
keycard-pairing notifications-enabled?
notifications-enabled?]} keycard-pairing]}
@(re-frame/subscribe [:multiaccount]) @(re-frame/subscribe [:multiaccount])
active-contacts-count @(re-frame/subscribe [:contacts/active-count]) active-contacts-count @(re-frame/subscribe [:contacts/active-count])
tribute-to-talk @(re-frame/subscribe [:tribute-to-talk/profile]) tribute-to-talk @(re-frame/subscribe [:tribute-to-talk/profile])
@ -126,16 +127,23 @@
:accessibility-label :appearance-settings-button :accessibility-label :appearance-settings-button
:chevron true :chevron true
:on-press #(re-frame/dispatch [:navigate-to :appearance])}] :on-press #(re-frame/dispatch [:navigate-to :appearance])}]
(when (and platform/android? (if platform/ios?
config/local-notifications?)
[quo/list-item [quo/list-item
{:icon :main-icons/notification {:icon :main-icons/notification
:title (i18n/label :t/notifications) :title (i18n/label :t/notifications)
:accessibility-label :notifications-button :accessibility-label :notifications-settings-button
:active notifications-enabled? :chevron true
:on-press #(re-frame/dispatch :on-press #(re-frame/dispatch [:navigate-to :notifications])}]
[:multiaccounts.ui/notifications-switched (not notifications-enabled?)]) (when (and platform/android?
:accessory :switch}]) 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 [quo/list-item
{:icon :main-icons/mobile {:icon :main-icons/mobile
:title (i18n/label :t/sync-settings) :title (i18n/label :t/sync-settings)

View File

@ -23,8 +23,8 @@
[quo.previews.main :as quo.preview] [quo.previews.main :as quo.preview]
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.ui.screens.chat.image.preview.views :as image-preview] [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 main-stack (navigation/create-stack))
(defonce bottom-tabs (navigation/create-bottom-tabs)) (defonce bottom-tabs (navigation/create-bottom-tabs))
@ -114,7 +114,12 @@
{:name :notifications-settings {:name :notifications-settings
:back-handler :noop :back-handler :noop
:insets {:bottom true} :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? (when config/quo-preview-enabled?
[{:name :quo-preview [{:name :quo-preview
:insets {:top false :bottom false} :insets {:top false :bottom false}

View File

@ -37,6 +37,7 @@
[status-im.ui.components.tabbar.styles :as tabbar.styles] [status-im.ui.components.tabbar.styles :as tabbar.styles]
[status-im.ui.screens.routing.core :as navigation] [status-im.ui.screens.routing.core :as navigation]
[status-im.ui.screens.appearance.views :as appearance] [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])) [status-im.ui.screens.privacy-and-security-settings.delete-profile :as delete-profile]))
(defonce stack (navigation/create-stack)) (defonce stack (navigation/create-stack))
@ -83,6 +84,10 @@
:component privacy-and-security/privacy-and-security} :component privacy-and-security/privacy-and-security}
{:name :appearance {:name :appearance
:component appearance/appearance} :component appearance/appearance}
{:name :notifications
:component notifications-settings/notifications-settings}
{:name :notifications-servers
:component notifications-settings/notifications-servers}
{:name :sync-settings {:name :sync-settings
:component sync-settings/sync-settings} :component sync-settings/sync-settings}
{:name :advanced-settings {:name :advanced-settings

View File

@ -46,6 +46,7 @@
(def log-level (def log-level
(string/upper-case (get-config :LOG_LEVEL ""))) (string/upper-case (get-config :LOG_LEVEL "")))
(def fleet (get-config :FLEET "eth.staging")) (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 default-network (get-config :DEFAULT_NETWORK))
(def pow-target (js/parseFloat (get-config :POW_TARGET "0.0001"))) (def pow-target (js/parseFloat (get-config :POW_TARGET "0.0001")))
(def pow-time (js/parseInt (get-config :POW_TIME "1"))) (def pow-time (js/parseInt (get-config :POW_TIME "1")))

View File

@ -2,7 +2,7 @@
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead", "_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
"owner": "status-im", "owner": "status-im",
"repo": "status-go", "repo": "status-go",
"version": "v0.60.2", "version": "v0.61.1",
"commit-sha1": "57728224d45ce3086e135988ae02e247abbc7b60", "commit-sha1": "61b345ff3395e4d031da1c4b497cc431a4ab2177",
"src-sha256": "1smgazlkgjxqq27ncgxagdi3523vcnmrca7lgj0lbxb4kbqgmmbl" "src-sha256": "1dg9w9fdi5isdc72ydxqgin6bg8b7jqkavjs2x8bvl9lhf2mqm3c"
} }

View File

@ -461,7 +461,7 @@ class AboutButton(BaseButton):
class PrifileNotificationsButton(BaseButton): class PrifileNotificationsButton(BaseButton):
def __init__(self, driver): def __init__(self, driver):
super().__init__(driver) super().__init__(driver)
self.locator = self.Locator.accessibility_id("notifications-button") self.locator = self.Locator.accessibility_id("notifications-settings-button")
class RemovePictureButton(BaseButton): class RemovePictureButton(BaseButton):

View File

@ -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-text": "The card you used is not a Keycard. You need to purchase a Keycard to use it",
"not-keycard-title": "Not a Keycard", "not-keycard-title": "Not a Keycard",
"notifications": "Notifications", "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", "notify": "Notify",
"off": "Off", "off": "Off",
"offline": "Offline", "offline": "Offline",
@ -960,6 +972,7 @@
"sharing-share": "Share", "sharing-share": "Share",
"show-less": "Show less", "show-less": "Show less",
"show-more": "Show more", "show-more": "Show more",
"show-notifications": "Show notifications",
"show-qr": "Show QR code", "show-qr": "Show QR code",
"show-transaction-data": "Show transaction data", "show-transaction-data": "Show transaction data",
"sign-and-send": "Sign and send", "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.", "private-notifications-descr": "Status will notify you about new messages. You can edit your notification preferences later in settings.",
"maybe-later": "Maybe later", "maybe-later": "Maybe later",
"join": "Join", "join": "Join",
"registered": "registered",
"not-registered": "not registered",
"audio-recorder-error": "Recorder error", "audio-recorder-error": "Recorder error",
"audio-recorder": "Recorder", "audio-recorder": "Recorder",
"audio-recorder-max-ms-reached": "Maximum recording time reached", "audio-recorder-max-ms-reached": "Maximum recording time reached",

View File

@ -1344,6 +1344,13 @@
resolved "https://registry.yarnpkg.com/@react-native-community/netinfo/-/netinfo-4.7.0.tgz#7482d36836cac69d0a0ae25581f65bc472639930" resolved "https://registry.yarnpkg.com/@react-native-community/netinfo/-/netinfo-4.7.0.tgz#7482d36836cac69d0a0ae25581f65bc472639930"
integrity sha512-a/sDB+AsLEUNmhAUlAaTYeXKyQdFGBUfatqKkX5jluBo2CB3OAuTHfm7rSjcaLB9EmG5iSq3fOTpync2E7EYTA== 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": "@react-native-community/slider@^3.0.0":
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/@react-native-community/slider/-/slider-3.0.0.tgz#ffbf78689fc0572fb5c1e2ccb61b2ef074d3dcd2" resolved "https://registry.yarnpkg.com/@react-native-community/slider/-/slider-3.0.0.tgz#ffbf78689fc0572fb5c1e2ccb61b2ef074d3dcd2"