account: add notification to settings

Change-Id: Ib9422b0dac62cad284bce57a3b0dd89ac8f90fcc
diff --git a/Ring/Ring/AppDelegate.swift b/Ring/Ring/AppDelegate.swift
index 824b0b4..02ff877 100644
--- a/Ring/Ring/AppDelegate.swift
+++ b/Ring/Ring/AppDelegate.swift
@@ -147,6 +147,9 @@
             if self.accountService.getCurrentProxyState(accountID: currentAccount.id) {
                 self.registerVoipNotifications()
             }
+            //in case if application was open when incoming call launched the push notifications
+            // reimit new call signal to show incoming call alert
+            self.callService.checkForIncomingCall()
         }.disposed(by: self.disposeBag)
 
         self.window?.rootViewController = self.appCoordinator.rootViewController
@@ -177,6 +180,7 @@
     }
 
     func applicationDidBecomeActive(_ application: UIApplication) {
+        self.callService.checkForIncomingCall()
         self.clearBadgeNumber()
     }
 
@@ -261,6 +265,11 @@
     }
 
     func handleNotificationActions(data: [AnyHashable: Any], responseIdentifier: String) {
+        // if notification contains messageContent this is message notification
+        if let participantID = data[NotificationUserInfoKeys.participantID.rawValue] as? String {
+            self.appCoordinator.openConversation(participantID: participantID)
+            return
+        }
         guard let callID = data[NotificationUserInfoKeys.callID.rawValue] as? String else {
             return
         }
@@ -275,7 +284,10 @@
                     print("Call ignored")
                 }).disposed(by: self.disposeBag)
         default:
-            print("Other Action")
+            // automatically answer call when user tap the notifications
+            NotificationCenter.default.post(name: NSNotification.Name(NotificationName.answerCallFromNotifications.rawValue),
+                                            object: nil,
+                                            userInfo: data)
         }
     }
 
@@ -286,9 +298,19 @@
         completionHandler()
     }
 
+    // handle notifications click before iOS 10.0
+    func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
+        guard let info = notification.userInfo else {return}
+        if (info[NotificationUserInfoKeys.callID.rawValue] as? String) != nil {
+             handleNotificationActions(data: info, responseIdentifier: CallAcition.accept.rawValue)
+        } else if (info[NotificationUserInfoKeys.messageContent.rawValue] as? String) != nil {
+            handleNotificationActions(data: info, responseIdentifier: "messageReceived")
+        }
+    }
+
     func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
         if let rootViewController = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController) {
-            if (rootViewController.responds(to: Selector(("canRotate")))) {
+            if rootViewController.responds(to: Selector(("canRotate"))) {
                 return .all
             }
         }
diff --git a/Ring/Ring/Coordinators/AppCoordinator.swift b/Ring/Ring/Coordinators/AppCoordinator.swift
index 980e32a..8ea1787 100644
--- a/Ring/Ring/Coordinators/AppCoordinator.swift
+++ b/Ring/Ring/Coordinators/AppCoordinator.swift
@@ -176,4 +176,11 @@
     private func showMainInterface () {
         self.navigationController.setViewControllers([self.tabBarViewController], animated: true)
     }
+
+    func openConversation (participantID: String) {
+        self.tabBarViewController.selectedIndex = 0
+        if let conversationCoordinator = self.childCoordinators[0] as? ConversationsCoordinator {
+            conversationCoordinator.puchConversation(participantId: participantID)
+        }
+    }
 }
diff --git a/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift b/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift
index 9fc1fe0..e231121 100644
--- a/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift
+++ b/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift
@@ -37,11 +37,15 @@
 
     let stateSubject = PublishSubject<State>()
     let callService: CallsService
+    let accountService: AccountsService
+    let conversationService: ConversationsService
 
     required init (with injectionBag: InjectionBag) {
         self.injectionBag = injectionBag
 
         self.callService = injectionBag.callService
+        self.accountService = injectionBag.accountService
+        self.conversationService = injectionBag.conversationsService
         self.addLockFlags()
 
         self.callService.newCall.asObservable()
@@ -63,6 +67,18 @@
         self.answerIncomingCall(call: call)
     }
 
+    func puchConversation(participantId: String) {
+        let conversationViewModel = ConversationViewModel(with: self.injectionBag)
+        guard let account = accountService.currentAccount else {
+            return
+        }
+        guard let conversation = self.conversationService.findConversation(withRingId: participantId, withAccountId: account.id) else {
+            return
+        }
+        conversationViewModel.conversation = Variable<ConversationModel>(conversation)
+        self.pushConversation(withConversationViewModel: conversationViewModel)
+    }
+
     func start () {
         let smartListViewController = SmartlistViewController.instantiate(with: self.injectionBag)
         self.present(viewController: smartListViewController, withStyle: .show, withAnimation: true, withStateable: smartListViewController.viewModel)
diff --git a/Ring/Ring/Features/Me/Me/MeViewController.swift b/Ring/Ring/Features/Me/Me/MeViewController.swift
index 3988434..758c960 100644
--- a/Ring/Ring/Features/Me/Me/MeViewController.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewController.swift
@@ -181,7 +181,7 @@
                         .observeOn(MainScheduler.instance)
                         .bind(to: cell.switchProxy.rx.isOn)
                         .disposed(by: cell.disposeBag)
-                    cell.switchProxy.rx.isOn
+                    cell.switchProxy.rx.value.skip(1)
                         .observeOn(MainScheduler.instance)
                         .subscribe(onNext: { [weak self] (enable) in
                             self?.viewModel.enableProxy(enable: enable)
diff --git a/Ring/Ring/Features/Me/Me/MeViewModel.swift b/Ring/Ring/Features/Me/Me/MeViewModel.swift
index 66257c2..f23a95f 100644
--- a/Ring/Ring/Features/Me/Me/MeViewModel.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewModel.swift
@@ -139,7 +139,7 @@
     lazy var accountSettings: Observable<SettingsSection> = {
         return Observable
             .just(.accountSettings( items: [.sectionHeader(title: L10n.Accountpage.settingsHeader),
-                                            .blockedList]))
+                                            .blockedList, .proxy]))
     }()
 
     lazy var linkedDevices: Observable<SettingsSection> = {
diff --git a/Ring/Ring/Features/Me/Me/ProxyCell.xib b/Ring/Ring/Features/Me/Me/ProxyCell.xib
index 7349d9d..859906d 100644
--- a/Ring/Ring/Features/Me/Me/ProxyCell.xib
+++ b/Ring/Ring/Features/Me/Me/ProxyCell.xib
@@ -21,7 +21,7 @@
                 <autoresizingMask key="autoresizingMask"/>
                 <subviews>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Enable DHT Proxy" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MDc-3P-GUZ">
-                        <rect key="frame" x="16" y="21" width="138" height="37.5"/>
+                        <rect key="frame" x="16" y="29.5" width="138" height="20.5"/>
                         <fontDescription key="fontDescription" type="system" pointSize="17"/>
                         <nil key="textColor"/>
                         <nil key="highlightedColor"/>
@@ -29,26 +29,12 @@
                     <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d2V-lG-agH">
                         <rect key="frame" x="245" y="24.5" width="51" height="31"/>
                     </switch>
-                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="1000" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4md-9M-D0t">
-                        <rect key="frame" x="15" y="77.5" width="290" height="1"/>
-                        <color key="backgroundColor" name="gridColor" catalog="System" colorSpace="catalog"/>
-                        <constraints>
-                            <constraint firstAttribute="height" constant="1" id="kmt-kk-p5x"/>
-                        </constraints>
-                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
-                        <nil key="textColor"/>
-                        <nil key="highlightedColor"/>
-                    </label>
                 </subviews>
                 <constraints>
                     <constraint firstItem="MDc-3P-GUZ" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="5Cc-zh-bge"/>
                     <constraint firstAttribute="trailingMargin" secondItem="d2V-lG-agH" secondAttribute="trailing" constant="10" id="C4A-h4-cb2"/>
                     <constraint firstItem="d2V-lG-agH" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="LLg-TR-ckG"/>
-                    <constraint firstAttribute="bottom" secondItem="4md-9M-D0t" secondAttribute="bottom" constant="1" id="Pg5-B1-z6A"/>
-                    <constraint firstItem="4md-9M-D0t" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="15" id="Uoe-5l-g8S"/>
-                    <constraint firstItem="MDc-3P-GUZ" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" constant="10" id="nfA-AL-Ki4"/>
                     <constraint firstItem="MDc-3P-GUZ" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" id="p2r-md-xAe"/>
-                    <constraint firstAttribute="trailing" secondItem="4md-9M-D0t" secondAttribute="trailing" constant="15" id="wrR-iQ-O6t"/>
                 </constraints>
             </tableViewCellContentView>
             <viewLayoutGuide key="safeArea" id="mTt-uZ-iJS"/>
diff --git a/Ring/Ring/Helpers/LocalNotificationsHelper.swift b/Ring/Ring/Helpers/LocalNotificationsHelper.swift
index d75e9f5..5c10754 100644
--- a/Ring/Ring/Helpers/LocalNotificationsHelper.swift
+++ b/Ring/Ring/Helpers/LocalNotificationsHelper.swift
@@ -24,6 +24,7 @@
     case callID
     case name
     case messageContent
+    case participantID
 }
 
 enum NotificationCallTitle: String {
@@ -63,6 +64,7 @@
             let content = UNMutableNotificationContent()
             content.title = title
             content.body = body
+            content.userInfo = data
             content.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber
             let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false)
             let identifier = Int64(arc4random_uniform(10000000))
@@ -76,6 +78,7 @@
             let notification = UILocalNotification()
             notification.alertTitle = title
             notification.alertBody = body
+            notification.userInfo = data
             notification.applicationIconBadgeNumber = UIApplication.shared.applicationIconBadgeNumber + 1
             UIApplication.shared.scheduleLocalNotification(notification)
         }
@@ -140,7 +143,7 @@
             let callID = data [NotificationUserInfoKeys.callID.rawValue] else {
                 return
         }
-        timer = Timer.scheduledTimer(timeInterval: 10,
+        timer = Timer.scheduledTimer(timeInterval: 60,
                                      target: self,
                                      selector: #selector(cancelCall),
                                      userInfo: [NotificationUserInfoKeys.callID.rawValue: callID],
@@ -151,7 +154,6 @@
             content.body = name
             content.userInfo = data
             content.categoryIdentifier = self.callCategory
-            content.sound = UNNotificationSound(named: "defaul.wav")
             let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false)
             let notificationRequest = UNNotificationRequest(identifier: callID, content: content, trigger: notificationTrigger)
             UNUserNotificationCenter.current().add(notificationRequest) { (error) in
diff --git a/Ring/Ring/Protocols/ConversationNavigation.swift b/Ring/Ring/Protocols/ConversationNavigation.swift
index 69a12e4..b1a1a4b 100644
--- a/Ring/Ring/Protocols/ConversationNavigation.swift
+++ b/Ring/Ring/Protocols/ConversationNavigation.swift
@@ -79,6 +79,20 @@
                      lockWhilePresenting: VCType.conversation.rawValue)
     }
 
+    func pushConversation(withConversationViewModel conversationViewModel: ConversationViewModel) {
+        if let flag = self.presentingVC[VCType.conversation.rawValue], flag {
+            return
+        }
+        self.presentingVC[VCType.conversation.rawValue] = true
+        let conversationViewController = ConversationViewController.instantiate(with: self.injectionBag)
+        conversationViewController.viewModel = conversationViewModel
+        self.present(viewController: conversationViewController,
+                     withStyle: .push,
+                     withAnimation: false,
+                     withStateable: conversationViewController.viewModel,
+                     lockWhilePresenting: VCType.conversation.rawValue)
+    }
+
     func startOutgoingCall(contactRingId: String, userName: String, isAudioOnly: Bool = false) {
         let callViewController = CallViewController.instantiate(with: self.injectionBag)
         callViewController.viewModel.placeCall(with: contactRingId, userName: userName, isAudioOnly: isAudioOnly)
diff --git a/Ring/Ring/Protocols/Coordinator.swift b/Ring/Ring/Protocols/Coordinator.swift
index 158eaf8..2c25414 100644
--- a/Ring/Ring/Protocols/Coordinator.swift
+++ b/Ring/Ring/Protocols/Coordinator.swift
@@ -34,6 +34,7 @@
     case present
     case popup
     case appear
+    case push
 }
 
 /// A Coordinator drives the navigation of a whole part of the application
@@ -106,6 +107,12 @@
             self.rootViewController.present(viewController,
                                             animated: animation,
                                             completion: nil)
+        case .push:
+            if let contoller: UINavigationController  = self.rootViewController as? UINavigationController {
+                // ensure we on the root view controller
+                contoller.popViewController(animated: false)
+                contoller.pushViewController(viewController, animated: false)
+            }
         }
 
         if let viewControllerType = VCType {
diff --git a/Ring/Ring/Services/AccountsService.swift b/Ring/Ring/Services/AccountsService.swift
index 6412641..95f9d24 100644
--- a/Ring/Ring/Services/AccountsService.swift
+++ b/Ring/Ring/Services/AccountsService.swift
@@ -507,7 +507,7 @@
     func enableProxy(accountID: String, enable: Bool) {
         let accountDetails = self.getAccountDetails(fromAccountId: accountID)
         accountDetails.set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.proxyEnabled), withValue: enable.toString())
-        let proxy = enable ? "192.168.51.6:8000" : ""
+        let proxy = enable ? "dhtproxy.ring.cx:80" : ""
         accountDetails.set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.proxyServer), withValue: proxy)
         self.setAccountDetails(forAccountId: accountID, withDetails: accountDetails)
         var event = ServiceEvent(withEventType: .proxyEnabled)
diff --git a/Ring/Ring/Services/CallsService.swift b/Ring/Ring/Services/CallsService.swift
index 177d958..68477e6 100644
--- a/Ring/Ring/Services/CallsService.swift
+++ b/Ring/Ring/Services/CallsService.swift
@@ -66,6 +66,12 @@
                                                object: nil)
     }
 
+    func checkForIncomingCall() {
+        if let call = self.call(callID: self.newCall.value.callId), call.state == .incoming {
+            self.newCall.value = call
+        }
+    }
+
     @objc func refuseUnansweredCall(_ notification: NSNotification) {
         guard let callid = notification.userInfo?[NotificationUserInfoKeys.callID.rawValue] as? String else {
             return
diff --git a/Ring/Ring/Services/ConversationsManager.swift b/Ring/Ring/Services/ConversationsManager.swift
index 129876c..9f420cf 100644
--- a/Ring/Ring/Services/ConversationsManager.swift
+++ b/Ring/Ring/Services/ConversationsManager.swift
@@ -130,6 +130,7 @@
         if UIApplication.shared.applicationState != .active {
             var data = [String: String]()
             data [NotificationUserInfoKeys.messageContent.rawValue] = content
+            data [NotificationUserInfoKeys.participantID.rawValue] = senderAccount
             self.nameService.usernameLookupStatus.single()
                 .filter({ lookupNameResponse in
                     return lookupNameResponse.address != nil &&