Commit 70ec95af authored by Kateryna Kostiuk's avatar Kateryna Kostiuk Committed by Andreas Traczyk

push notifications: initial implementation

This patch adds support for push notifications and DHT Proxy.

Change-Id: I4aa9f4c59a8c7c504638b7cc2287cede6dfb5c00
Reviewed-by: Andreas Traczyk's avatarAndreas Traczyk <andreas.traczyk@savoirfairelinux.com>
parent e9886c8a
......@@ -121,6 +121,8 @@
0E983E6E1FC77C3E0082103E /* ConversationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E983E6D1FC77C3E0082103E /* ConversationModel.swift */; };
0E9D84491FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */; };
0E9D844B1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9D844A1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift */; };
0EAA9DB42029F0AA005E245C /* ProxyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAA9DB22029F0AA005E245C /* ProxyCell.swift */; };
0EAA9DB52029F0AA005E245C /* ProxyCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0EAA9DB32029F0AA005E245C /* ProxyCell.xib */; };
0EB1A5CF1F8EBE03009923E2 /* DeviceCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0EB1A5CE1F8EBE03009923E2 /* DeviceCell.xib */; };
0EB1A5D11F8EBE23009923E2 /* DeviceCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB1A5D01F8EBE23009923E2 /* DeviceCell.swift */; };
0EB479951FA28A7300106AFD /* ButtonTransparentBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB479941FA28A7300106AFD /* ButtonTransparentBackground.swift */; };
......@@ -380,6 +382,7 @@
0E4909741FEAC943005CAA50 /* CallViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = CallViewController.storyboard; sourceTree = "<group>"; };
0E4909791FEAC9E1005CAA50 /* CallViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallViewController.swift; sourceTree = "<group>"; };
0E49097B1FEACA4B005CAA50 /* CallViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallViewModel.swift; sourceTree = "<group>"; };
0E63F1F3202907090001F248 /* Ring.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Ring.entitlements; sourceTree = "<group>"; };
0E68571020238546008B0717 /* CallMakeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallMakeable.swift; sourceTree = "<group>"; };
0E6949781FA7E71C0029B60A /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = "<group>"; };
0E7CF4DA20164B6700CD967D /* ButtonsContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonsContainerView.swift; sourceTree = "<group>"; };
......@@ -388,6 +391,8 @@
0E983E6D1FC77C3E0082103E /* ConversationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationModel.swift; sourceTree = "<group>"; };
0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatTabBarItemViewModel.swift; sourceTree = "<group>"; };
0E9D844A1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactRequestTabBarItem.swift; sourceTree = "<group>"; };
0EAA9DB22029F0AA005E245C /* ProxyCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyCell.swift; sourceTree = "<group>"; };
0EAA9DB32029F0AA005E245C /* ProxyCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ProxyCell.xib; sourceTree = "<group>"; };
0EB1A5CE1F8EBE03009923E2 /* DeviceCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DeviceCell.xib; sourceTree = "<group>"; };
0EB1A5D01F8EBE23009923E2 /* DeviceCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceCell.swift; sourceTree = "<group>"; };
0EB479941FA28A7300106AFD /* ButtonTransparentBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonTransparentBackground.swift; sourceTree = "<group>"; };
......@@ -847,6 +852,7 @@
043999F51D1C2D9D00E99CD9 /* Ring */ = {
isa = PBXGroup;
children = (
0E63F1F3202907090001F248 /* Ring.entitlements */,
0E0FF1A81FC38409003898C2 /* Database */,
02E1A0261DDE4C2E00D75B59 /* Services */,
1A2D18B81F2916BA00B2C785 /* Models */,
......@@ -993,6 +999,7 @@
0E5AFE0A1F8EBC040040D539 /* Cells */ = {
isa = PBXGroup;
children = (
0EAA9DAD2029F054005E245C /* Proxy */,
0E5AFE0B1F8EBC1E0040D539 /* DeviceCell */,
);
name = Cells;
......@@ -1019,6 +1026,15 @@
path = TabBar;
sourceTree = "<group>";
};
0EAA9DAD2029F054005E245C /* Proxy */ = {
isa = PBXGroup;
children = (
0EAA9DB22029F0AA005E245C /* ProxyCell.swift */,
0EAA9DB32029F0AA005E245C /* ProxyCell.xib */,
);
name = Proxy;
sourceTree = "<group>";
};
0ED2B6F81F96A048001572F0 /* LinknewDevice */ = {
isa = PBXGroup;
children = (
......@@ -1408,7 +1424,10 @@
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.BackgroundModes = {
enabled = 0;
enabled = 1;
};
com.apple.Push = {
enabled = 1;
};
};
};
......@@ -1517,6 +1536,7 @@
0E2D5F551F9145F200D574BF /* LinkNewDeviceCell.xib in Resources */,
1A2D18ED1F2919D800B2C785 /* MeViewController.storyboard in Resources */,
1A20417E1F1E8DDA00C08435 /* CreateProfileViewController.storyboard in Resources */,
0EAA9DB52029F0AA005E245C /* ProxyCell.xib in Resources */,
1ABE07DF1F0D91A800D36361 /* LaunchScreen.storyboard in Resources */,
1A5DC0381F35675E0075E8EF /* ContactRequestCell.xib in Resources */,
1A0C4EDA1F1D4B1B00550433 /* WelcomeViewController.storyboard in Resources */,
......@@ -1743,6 +1763,7 @@
564C44621E943DE6000F92B1 /* NameService.swift in Sources */,
1A5DC02C1F3565250075E8EF /* MeViewController.swift in Sources */,
0EF78DE31FD0AE3000FC6966 /* ConversationsManager.swift in Sources */,
0EAA9DB42029F0AA005E245C /* ProxyCell.swift in Sources */,
1A2041801F1E903B00C08435 /* CreateProfileViewController.swift in Sources */,
0E0FF1B71FC398B3003898C2 /* ConversationDataHepler.swift in Sources */,
62DFAB2E1F9FF0D0002D6F9C /* NetworkService.swift in Sources */,
......@@ -1973,6 +1994,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "compiler-default";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Ring/Ring.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
......@@ -2009,6 +2031,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "compiler-default";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Ring/Ring.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
......@@ -2167,6 +2190,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_CXX_LIBRARY = "compiler-default";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Ring/Ring.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
......
......@@ -25,10 +25,10 @@ import SwiftyBeaver
import RxSwift
import Chameleon
import Contacts
import PushKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
private let daemonService = DaemonService(dRingAdaptor: DRingAdapter())
private let accountService = AccountsService(withAccountAdapter: AccountAdapter())
......@@ -43,6 +43,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
private var conversationManager: ConversationsManager?
private var contactRequestManager: ContactRequestManager?
private let voipRegistry = PKPushRegistry(queue: DispatchQueue.main)
public lazy var injectionBag: InjectionBag = {
return InjectionBag(withDaemonService: self.daemonService,
withAccountService: self.accountService,
......@@ -117,11 +119,21 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
let accountDetails = self.accountService.getAccountDetails(fromAccountId: currentAccount.id)
accountDetails.set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.videoEnabled), withValue: "true")
self.accountService.setAccountDetails(forAccountId: currentAccount.id, withDetails: accountDetails)
if self.accountService.getCurrentProxyState(accountID: currentAccount.id) {
self.registerVoipNotifications()
}
}.disposed(by: self.disposeBag)
self.window?.rootViewController = self.appCoordinator.rootViewController
self.window?.makeKeyAndVisible()
self.appCoordinator.start()
self.voipRegistry.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(registerVoipNotifications),
name: NSNotification.Name(rawValue: NotificationName.enablePushNotifications.rawValue),
object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(unregisterVoipNotifications),
name: NSNotification.Name(rawValue: NotificationName.disablePushNotifications.rawValue),
object: nil)
return true
}
......@@ -177,4 +189,45 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
}
}
@objc private func registerVoipNotifications() {
self.requestNotificationAuthorization()
self.voipRegistry.desiredPushTypes = Set([PKPushType.voIP])
}
@objc private func unregisterVoipNotifications() {
self.voipRegistry.desiredPushTypes = nil
self.accountService.setPushNotificationToken(token: "")
}
func requestNotificationAuthorization() {
let application = UIApplication.shared
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = application.delegate as? UNUserNotificationCenterDelegate
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions, completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
}
}
extension AppDelegate: PKPushRegistryDelegate {
func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
self.accountService.setPushNotificationToken(token: "")
}
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
self.accountService.pushNotificationReceived(data: payload.dictionaryPayload)
}
func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
if type == PKPushType.voIP {
let deviceTokenString = pushCredentials.token.map { String(format: "%02.2hhx", $0) }.joined()
self.accountService.updatePushTokenForCurrentAccount(token: deviceTokenString)
self.accountService.setPushNotificationToken(token: deviceTokenString)
}
}
}
......@@ -68,4 +68,7 @@
- (Boolean)exportOnRing:(NSString *)accountID
password: (NSString *)password;
- (void)pushNotificationReceived:(NSString *) from message:(NSDictionary*) data;
- (void)setPushNotificationToken: (NSString *) token;
@end
......@@ -152,4 +152,11 @@ static id <AccountAdapterDelegate> _delegate;
return exportOnRing(std::string([accountID UTF8String]), std::string([password UTF8String]));
}
- (void)pushNotificationReceived:(NSString*)from message:(NSDictionary*)data {
pushNotificationReceived(std::string([from UTF8String]), [Utils dictionnaryToMap:data]);
}
- (void)setPushNotificationToken: (NSString*)token {
setPushNotificationToken(std::string([token UTF8String]));
}
@end
......@@ -38,3 +38,5 @@
#import <CommonCrypto/CommonCrypto.h>
#import <Contacts/Contacts.h>
#import "CallsAdapter.h"
#import <PushKit/PushKit.h>
#import <UserNotifications/UserNotifications.h>
......@@ -11,6 +11,10 @@ enum L10n {
enum Accountpage {
/// Devices
static let devicesListHeader = L10n.tr("Localizable", "accountPage.devicesListHeader")
/// Enable Push Notifications
static let enableProxy = L10n.tr("Localizable", "accountPage.enableProxy")
/// Settings
static let settingsHeader = L10n.tr("Localizable", "accountPage.settingsHeader")
}
enum Actions {
......
......@@ -73,6 +73,7 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
self.setUpDataSource()
self.settingsTable.register(cellType: DeviceCell.self)
self.settingsTable.register(cellType: LinkNewDeviceCell.self)
self.settingsTable.register(cellType: ProxyCell.self)
}
func infoItemTapped() {
......@@ -119,6 +120,23 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
}).disposed(by: cell.disposeBag)
cell.selectionStyle = .none
return cell
case .proxy:
let cell = tableView.dequeueReusableCell(for: indexPath,
cellType: ProxyCell.self)
cell.enableProxyLabel.text = L10n.Accountpage.enableProxy
cell.switchProxy.isOn = self.viewModel.proxyInitialState
self.viewModel.proxyEnabled?
.observeOn(MainScheduler.instance)
.bind(to: cell.switchProxy.rx.isOn)
.disposed(by: cell.disposeBag)
cell.switchProxy.rx.isOn
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [unowned self] (enable) in
self.viewModel.enableProxy(enable: enable)
}).disposed(by: cell.disposeBag)
cell.selectionStyle = .none
return cell
}
}
......
......@@ -29,10 +29,12 @@ enum SettingsSection: SectionModelType {
case linkedDevices(header: String, items: [SectionRow])
case linkNewDevice(header: String, items: [SectionRow])
case enableProxy(header: String, items: [SectionRow])
enum SectionRow {
case device(device: DeviceModel)
case linkNew
case proxy
}
var header: String {
......@@ -44,6 +46,8 @@ enum SettingsSection: SectionModelType {
case .linkNewDevice(let header, _):
return header
case .enableProxy(let header, _):
return header
}
}
......@@ -54,6 +58,9 @@ enum SettingsSection: SectionModelType {
case .linkNewDevice(_, let items):
return items
case .enableProxy(_, let items):
return items
}
}
......@@ -64,6 +71,9 @@ enum SettingsSection: SectionModelType {
case .linkNewDevice(let header, _):
self = .linkNewDevice(header: header, items: items)
case .enableProxy(let header, _):
self = .enableProxy(header: header, items: items)
}
}
}
......@@ -130,6 +140,7 @@ class MeViewModel: ViewModel, Stateable {
return devices.concat(accountDevice)
.map { devices in
let addNewDevice = SettingsSection.linkNewDevice(header: "", items: [SettingsSection.SectionRow.linkNew])
let enableProxy = SettingsSection.enableProxy(header: L10n.Accountpage.settingsHeader, items: [SettingsSection.SectionRow.proxy])
var rows: [SettingsSection.SectionRow]?
if !devices.isEmpty {
......@@ -142,15 +153,29 @@ class MeViewModel: ViewModel, Stateable {
if rows != nil {
let devicesSection = SettingsSection.linkedDevices(header: L10n.Accountpage.devicesListHeader, items: rows!)
return [devicesSection, addNewDevice]
return [devicesSection, addNewDevice, enableProxy]
} else {
return [addNewDevice]
return [addNewDevice, enableProxy]
}
}
}
return Observable.just([SettingsSection]())
}()
lazy var proxyEnabled: Observable<Bool>? = {
if let account = self.accountService.currentAccount {
return self.accountService.proxyEnabled(accountID: account.id)
}
return nil
}()
lazy var proxyInitialState: Bool = {
if let account = self.accountService.currentAccount {
return self.accountService.getCurrentProxyState(accountID: account.id)
}
return false
}()
required init (with injectionBag: InjectionBag) {
self.accountService = injectionBag.accountService
self.nameService = injectionBag.nameService
......@@ -159,4 +184,11 @@ class MeViewModel: ViewModel, Stateable {
func linkDevice() {
self.stateSubject.onNext(MeState.linkNewDevice)
}
func enableProxy(enable: Bool) {
guard let account = self.accountService.currentAccount else {
return
}
self.accountService.changeProxyAvailability(accountID: account.id, enable: enable)
}
}
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
*
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import UIKit
import Reusable
import RxSwift
class ProxyCell: UITableViewCell, NibReusable {
@IBOutlet weak var enableProxyLabel: UILabel!
@IBOutlet weak var switchProxy: UISwitch!
var disposeBag = DisposeBag()
override func prepareForReuse() {
self.disposeBag = DisposeBag()
}
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="57" id="KGk-i7-Jjw" customClass="ProxyCell" customModule="Ring" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="320" height="57"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="320" height="56.5"/>
<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="18" width="138" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<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="12" width="51" height="31"/>
</switch>
</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 firstItem="MDc-3P-GUZ" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" id="p2r-md-xAe"/>
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<connections>
<outlet property="enableProxyLabel" destination="MDc-3P-GUZ" id="tjq-vo-mX0"/>
<outlet property="switchProxy" destination="d2V-lG-agH" id="yh7-7a-Dzs"/>
</connections>
<point key="canvasLocation" x="0.0" y="152.5"/>
</tableViewCell>
</objects>
</document>
......@@ -28,6 +28,12 @@
<string>The microphone will be used for communication during a call.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Used to let the user choose a profile picture</string>
<key>UIBackgroundModes</key>
<array>
<string>voip</string>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
......
......@@ -97,6 +97,9 @@ enum ConfigKey: String {
case ringNsURI = "RingNS.uri"
case accountPresenceSubscribeSupported = "Account.presenceSubscribeSupported"
case accountDeviceName = "Account.deviceName"
case proxyEnabled = "Account.proxyEnabled"
case proxyServer = "Account.proxyServer"
case devicePushToken = "Account.proxyPushToken"
}
/**
......
......@@ -105,6 +105,8 @@
//Account Page
"accountPage.devicesListHeader" = "Devices";
"accountPage.settingsHeader" = "Settings";
"accountPage.enableProxy" = "Enable Push Notifications";
//Link New Device
"linkDevice.title" = "Link a new device";
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>
......@@ -33,6 +33,11 @@ enum AddAccountError: Error {
case unknownError
}
enum NotificationName: String {
case enablePushNotifications
case disablePushNotifications
}
class AccountsService: AccountAdapterDelegate {
// MARK: Private members
......@@ -479,4 +484,85 @@ class AccountsService: AccountAdapterDelegate {
}
}
func setPushNotificationToken(token: String) {
self.accountAdapter.setPushNotificationToken(token)
}
func pushNotificationReceived(data: [AnyHashable: Any]) {
var notificationData = [String: String]()
for key in data.keys {
if let value = data[key] {
let valueString = String(describing: value)
let keyString = String(describing: key)
notificationData[keyString] = valueString
}
}
self.accountAdapter.pushNotificationReceived("", message: notificationData)
}
// MARK: DHT Proxy
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" : ""
accountDetails.set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.proxyServer), withValue: proxy)
self.setAccountDetails(forAccountId: accountID, withDetails: accountDetails)
var event = ServiceEvent(withEventType: .proxyEnabled)
event.addEventInput(.state, value: enable)
event.addEventInput(.accountId, value: accountID)
self.responseStream.onNext(event)
}
func getCurrentProxyState(accountID: String) -> Bool {
var proxyEnabled = false
let accountDetails = self.getAccountDetails(fromAccountId: accountID)
if accountDetails.get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.proxyEnabled)) == "true" {
proxyEnabled = true
}
return proxyEnabled
}
func proxyEnabled(accountID: String) -> Observable<Bool> {
let proxyChanged: Observable<Bool> = self.sharedResponseStream
.filter({ event in
if let accountId: String = event.getEventInput(.accountId) {
return event.eventType == ServiceEventType.proxyEnabled
&& accountId == accountID
}
return false
}).map({ event in
if let state: Bool = event.getEventInput(.state) {
return state
}
return false
})
.asObservable()
return proxyChanged
}
func changeProxyAvailability(accountID: String, enable: Bool) {
let proxyState = self.getCurrentProxyState(accountID: accountID)
if proxyState == enable {
return
}
self.enableProxy(accountID: accountID, enable: enable)
//enable push notifications
if enable {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: NotificationName.enablePushNotifications.rawValue), object: nil)
return
}
NotificationCenter.default.post(name: NSNotification.Name(rawValue: NotificationName.disablePushNotifications.rawValue), object: nil)
}
func updatePushTokenForCurrentAccount(token: String) {
guard let account = self.currentAccount else {
return
}
let accountDetails = self.getAccountDetails(fromAccountId: account.id)
accountDetails.set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.devicePushToken), withValue: token)
self.setAccountDetails(forAccountId: account.id, withDetails: accountDetails)
}
}
......@@ -37,6 +37,7 @@ enum ServiceEventType {
case contactRequestReceived
case contactRequestDiscarded
case profileUpdated
case proxyEnabled
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment