Commit 8f936d58 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk Committed by Andreas Traczyk

settings: add proxy

Change-Id: Ibeb8660e720f756342e05a8c95a02af0b07bfc62
parent 654f5aea
......@@ -104,6 +104,8 @@
0E20E4C82031FF560087C868 /* BlockContactsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E20E4C62031FF560087C868 /* BlockContactsCell.xib */; };
0E2D5F531F9145C800D574BF /* LinkNewDeviceCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E2D5F521F9145C800D574BF /* LinkNewDeviceCell.swift */; };
0E2D5F551F9145F200D574BF /* LinkNewDeviceCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E2D5F541F9145F200D574BF /* LinkNewDeviceCell.xib */; };
0E35C10C2077DFF000BBA5E3 /* NotificationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E35C10A2077DFF000BBA5E3 /* NotificationCell.swift */; };
0E35C10D2077DFF000BBA5E3 /* NotificationCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E35C10B2077DFF000BBA5E3 /* NotificationCell.xib */; };
0E36979920322D46009A68CA /* BlockListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E36979720322D46009A68CA /* BlockListViewController.swift */; };
0E36979D20322D75009A68CA /* BlockListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E36979C20322D75009A68CA /* BlockListViewModel.swift */; };
0E36979F20322E6F009A68CA /* BlockListViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E36979E20322E6F009A68CA /* BlockListViewController.storyboard */; };
......@@ -405,6 +407,8 @@
0E20E4C62031FF560087C868 /* BlockContactsCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BlockContactsCell.xib; sourceTree = "<group>"; };
0E2D5F521F9145C800D574BF /* LinkNewDeviceCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkNewDeviceCell.swift; sourceTree = "<group>"; };
0E2D5F541F9145F200D574BF /* LinkNewDeviceCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LinkNewDeviceCell.xib; sourceTree = "<group>"; };
0E35C10A2077DFF000BBA5E3 /* NotificationCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCell.swift; sourceTree = "<group>"; };
0E35C10B2077DFF000BBA5E3 /* NotificationCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NotificationCell.xib; sourceTree = "<group>"; };
0E36979720322D46009A68CA /* BlockListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockListViewController.swift; sourceTree = "<group>"; };
0E36979C20322D75009A68CA /* BlockListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockListViewModel.swift; sourceTree = "<group>"; };
0E36979E20322E6F009A68CA /* BlockListViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = BlockListViewController.storyboard; sourceTree = "<group>"; };
......@@ -1075,6 +1079,15 @@
name = BlockListCell;
sourceTree = "<group>";
};
0E35C1092077CE1400BBA5E3 /* PushNotifications */ = {
isa = PBXGroup;
children = (
0E35C10A2077DFF000BBA5E3 /* NotificationCell.swift */,
0E35C10B2077DFF000BBA5E3 /* NotificationCell.xib */,
);
name = PushNotifications;
sourceTree = "<group>";
};
0E36979B20322D4D009A68CA /* BlockList */ = {
isa = PBXGroup;
children = (
......@@ -1125,6 +1138,7 @@
0E5AFE0A1F8EBC040040D539 /* Cells */ = {
isa = PBXGroup;
children = (
0E35C1092077CE1400BBA5E3 /* PushNotifications */,
0E20E4C22031FEFF0087C868 /* BlockListCell */,
0EAA9DAD2029F054005E245C /* Proxy */,
0E5AFE0B1F8EBC1E0040D539 /* DeviceCell */,
......@@ -1691,6 +1705,7 @@
1A2041841F1EA0FC00C08435 /* CreateAccountViewController.storyboard in Resources */,
0E2D5F551F9145F200D574BF /* LinkNewDeviceCell.xib in Resources */,
1A2D18ED1F2919D800B2C785 /* MeViewController.storyboard in Resources */,
0E35C10D2077DFF000BBA5E3 /* NotificationCell.xib in Resources */,
1A20417E1F1E8DDA00C08435 /* CreateProfileViewController.storyboard in Resources */,
0EAA9DB52029F0AA005E245C /* ProxyCell.xib in Resources */,
1ABE07DF1F0D91A800D36361 /* LaunchScreen.storyboard in Resources */,
......@@ -1783,7 +1798,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [ \"${CONFIGURATION}\" != \"Release\" ]; then\n if which swiftlint > /dev/null; then\n swiftlint\n else\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\n fi\nfi";
shellScript = "if [ \\\"${CONFIGURATION}\\\" != \\\"Release\\\" ]; then\n if which swiftlint > /dev/null; then\n swiftlint\n else\n echo \\\"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\\\"\n fi\nfi;";
};
1ABE07C41F0D779F00D36361 /* ⚙️ SwiftGen Code Generation */ = {
isa = PBXShellScriptBuildPhase;
......@@ -1967,6 +1982,7 @@
1A5DC0301F3565AE0075E8EF /* SmartlistViewController.swift in Sources */,
1A2D18A21F27A6D600B2C785 /* LinkDeviceViewModel.swift in Sources */,
564C44601E943C37000F92B1 /* NameRegistrationAdapter.mm in Sources */,
0E35C10C2077DFF000BBA5E3 /* NotificationCell.swift in Sources */,
0E8E9A0520483E1200DA8E8B /* TitleView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
......
......@@ -144,7 +144,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
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) {
let notificationsEnabled = accountDetails.get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.devicePushToken)).isEmpty ? false : true
if notificationsEnabled {
self.registerVoipNotifications()
}
//in case if application was open when incoming call launched the push notifications
......@@ -173,6 +174,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
func applicationWillEnterForeground(_ application: UIApplication) {
self.log.warning("entering foreground")
self.daemonService.connectivityChanged()
self.updateNotificationAvailability()
}
func applicationWillTerminate(_ application: UIApplication) {
......@@ -224,6 +226,29 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}
}
func updateNotificationAvailability() {
let enabled = LocalNotificationsHelper.isEnabled()
if #available(iOS 10.0, *) {
let currentSettings = UNUserNotificationCenter.current()
currentSettings.getNotificationSettings(completionHandler: { settings in
switch settings.authorizationStatus {
case .notDetermined:
break
case .denied:
if enabled { LocalNotificationsHelper.setNotification(enable: false) }
case .authorized:
if !enabled { LocalNotificationsHelper.setNotification(enable: true)}
}
})
} else {
if UIApplication.shared.isRegisteredForRemoteNotifications {
if !enabled {LocalNotificationsHelper.setNotification(enable: true)}
} else {
if enabled {LocalNotificationsHelper.setNotification(enable: false)}
}
}
}
@objc private func registerVoipNotifications() {
self.requestNotificationAuthorization()
self.voipRegistry.desiredPushTypes = Set([PKPushType.voIP])
......@@ -231,21 +256,39 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
@objc private func unregisterVoipNotifications() {
self.voipRegistry.desiredPushTypes = nil
self.accountService.setPushNotificationToken(token: "")
self.accountService.setPushNotificationToken(token: "")
self.accountService.updatePushTokenForCurrentAccount(token: "")
}
private 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 })
DispatchQueue.main.async {
UNUserNotificationCenter.current().delegate = application.delegate as? UNUserNotificationCenterDelegate
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions, completionHandler: { (enable, _) in
if enable {
LocalNotificationsHelper.setNotification(enable: true)
} else {
LocalNotificationsHelper.setNotification(enable: false)
}
})
}
} else {
let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
}
func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
let enabled = notificationSettings.types.contains(.alert)
if enabled {
LocalNotificationsHelper.setNotification(enable: true)
} else {
LocalNotificationsHelper.setNotification(enable: false)
}
}
private func clearBadgeNumber() {
UIApplication.shared.applicationIconBadgeNumber = 0
if #available(iOS 10.0, *) {
......@@ -336,6 +379,7 @@ extension AppDelegate: PKPushRegistryDelegate {
func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
self.accountService.setPushNotificationToken(token: "")
self.accountService.updatePushTokenForCurrentAccount(token: "")
}
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
......
......@@ -15,8 +15,22 @@ internal enum L10n {
internal static let credentialsHeader = L10n.tr("Localizable", "accountPage.credentialsHeader")
/// Devices
internal static let devicesListHeader = L10n.tr("Localizable", "accountPage.devicesListHeader")
/// Enable Push Notifications
/// Enable Notifications
internal static let enableNotifications = L10n.tr("Localizable", "accountPage.enableNotifications")
/// Enable Proxy
internal static let enableProxy = L10n.tr("Localizable", "accountPage.enableProxy")
/// Your device won't receive notifications when proxy is disabled
internal static let noProxyExplanationLabel = L10n.tr("Localizable", "accountPage.noProxyExplanationLabel")
/// Provide proxy address
internal static let proxyAddressAlert = L10n.tr("Localizable", "accountPage.proxyAddressAlert")
/// In oreder to receive notifications, please enable proxy
internal static let proxyDisabledAlertBody = L10n.tr("Localizable", "accountPage.proxyDisabledAlertBody")
/// Proxy Server Disabled
internal static let proxyDisabledAlertTitle = L10n.tr("Localizable", "accountPage.proxyDisabledAlertTitle")
/// Proxy address
internal static let proxyPaceholder = L10n.tr("Localizable", "accountPage.proxyPaceholder")
/// Save
internal static let saveProxyAddress = L10n.tr("Localizable", "accountPage.saveProxyAddress")
/// Settings
internal static let settingsHeader = L10n.tr("Localizable", "accountPage.settingsHeader")
/// UNBLOCK
......
......@@ -47,6 +47,22 @@ extension UIViewController {
return nil
}
func findPathWithActiveTextField(in table: UITableView) -> IndexPath? {
if table.numberOfSections <= 0 {return nil}
for i in 0..<table.numberOfSections {
if table.numberOfRows(inSection: i) == 0 {return nil}
for k in 0..<table.numberOfRows(inSection: i) {
let path = IndexPath(row: k, section: i)
if let row = table.cellForRow(at: path) {
if self.findActiveTextField(in: row) != nil {
return path
}
}
}
}
return nil
}
/// Scroll the UIScrollView to the right position
/// according to keyboard's height
///
......@@ -76,6 +92,37 @@ extension UIViewController {
}
func adaptTableToKeyboardState (for tableView: UITableView, with disposeBag: DisposeBag, topOffset: CGFloat? = nil, bottomOffset: CGFloat? = nil) {
NotificationCenter.keyboardHeight.observeOn(MainScheduler.instance).subscribe(onNext: { [unowned self, unowned tableView] (height) in
let trueHeight = height > 0 ? height + 100 : 0.0
// reset insets if they were changed before
if tableView.contentInset.bottom > 0 && trueHeight <= 0 {
var contentInsets = tableView.contentInset
contentInsets.bottom = 0
tableView.contentInset = contentInsets
if let topOffset = topOffset {
var contentOffset = tableView.contentOffset
contentOffset.y = -topOffset
tableView.setContentOffset(contentOffset, animated: false)
}
}
if let activeFieldRowPath = self.findPathWithActiveTextField(in: tableView), let cell = tableView.cellForRow(at: activeFieldRowPath) {
var contentInsets = tableView.contentInset
if trueHeight > 0 {
contentInsets.bottom += height
tableView.contentInset = contentInsets
}
var aRect = self.view.frame
aRect.size.height -= trueHeight
if !aRect.contains(cell.frame.origin) {
tableView.scrollToRow(at: activeFieldRowPath, at: .top, animated: true)
}
}
}).disposed(by: disposeBag)
}
func configureRingNavigationBar() {
self.navigationController?.navigationBar.barTintColor = UIColor.ringNavigationBar
self.navigationController?.navigationBar.layer.shadowColor = UIColor.black.cgColor
......
......@@ -43,6 +43,7 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
self.navigationItem.title = L10n.Global.meTabBarTitle
self.configureBindings()
self.configureRingNavigationBar()
self.adaptTableToKeyboardState(for: self.settingsTable, with: self.disposeBag, topOffset: self.stretchyHeader.minimumContentHeight)
}
override func viewWillAppear(_ animated: Bool) {
......@@ -99,6 +100,7 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
self.settingsTable.register(cellType: LinkNewDeviceCell.self)
self.settingsTable.register(cellType: ProxyCell.self)
self.settingsTable.register(cellType: BlockContactsCell.self)
self.settingsTable.register(cellType: NotificationCell.self)
self.settingsTable.rx.itemSelected
//.throttle(RxTimeInterval(2), scheduler: MainScheduler.instance)
......@@ -175,18 +177,37 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
case .proxy:
let cell = tableView.dequeueReusableCell(for: indexPath,
cellType: ProxyCell.self)
cell.proxyAddrsss.placeholder = L10n.Accountpage.proxyPaceholder
cell.enableProxyLabel.text = L10n.Accountpage.enableProxy
cell.switchProxy.isOn = self.viewModel.proxyInitialState
self.viewModel.proxyEnabled?
.observeOn(MainScheduler.instance)
.bind(to: cell.switchProxy.rx.isOn)
cell.proxyAddrsss.enablesReturnKeyAutomatically = true
self.viewModel.proxyEnabled.asDriver()
.drive(cell.switchProxy.rx.isOn)
.disposed(by: cell.disposeBag)
cell.switchProxy.rx.value.skip(1)
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] (enable) in
self?.viewModel.enableProxy(enable: enable)
if enable {
self?.askProxyAddressAlert()
return
}
self?.viewModel.changeProxyAvailability(enable: enable, proxyAddress: "")
}).disposed(by: cell.disposeBag)
cell.selectionStyle = .none
cell.proxyAddrsss.rx.controlEvent(.editingDidEndOnExit)
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] _ in
if let text = cell.proxyAddrsss.text, !text.isEmpty {
self?.viewModel.changeProxyAddress(address: text)
} else {
cell.proxyAddrsss.text = self?.viewModel.proxyAddress.value
}
}).disposed(by: cell.disposeBag)
self.viewModel.proxyDisplaybele.asDriver(onErrorJustReturn: "")
.drive(cell.proxyAddrsss.rx.text)
.disposed(by: cell.disposeBag)
self.viewModel.proxyEnabled.asDriver()
.drive(cell.proxyAddrsss.rx.isEnabled)
.disposed(by: cell.disposeBag)
return cell
case .blockedList:
......@@ -207,6 +228,25 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
cell.textLabel?.text = label
cell.selectionStyle = .none
return cell
case .notifications:
let cell = tableView.dequeueReusableCell(for: indexPath,
cellType: NotificationCell.self)
cell.selectionStyle = .none
cell.enableNotificationsLabel.text = L10n.Accountpage.enableNotifications
self.viewModel.notificationsEnabled.asDriver()
.drive(cell.enableNotificationsSwitch.rx.value)
.disposed(by: cell.disposeBag)
cell.enableNotificationsSwitch.rx.value.skip(1)
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] (enable) in
guard let proxyEnabled = self?.viewModel.proxyEnabled.value else {return}
if enable && !proxyEnabled {
self?.proxyDisabledAlert()
return
}
self?.viewModel.enablePushNotifications(enable: enable)
}).disposed(by: cell.disposeBag)
return cell
}
}
......@@ -216,9 +256,63 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
.disposed(by: disposeBag)
}
func proxyDisabledAlert() {
let alert = UIAlertController(title: L10n.Accountpage.proxyDisabledAlertTitle,
message: L10n.Accountpage.proxyDisabledAlertBody,
preferredStyle: .alert)
let actionCancel = UIAlertAction(title: L10n.Global.ok, style: .cancel) { [weak self]_ in
self?.viewModel.notificationsEnabled.value = false
self?.dismiss(animated: true, completion: nil)
}
alert.addAction(actionCancel)
self.present(alert, animated: true, completion: nil)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
resetProfileName()
self.profileName.resignFirstResponder()
if let activeField = self.findActiveTextField(in: settingsTable) {
activeField.resignFirstResponder()
// now the only possible active text field is proxy address, ensure it is not empty
if let text = activeField.text, text.isEmpty {
self.viewModel.proxyAddress.value = self.viewModel.proxyAddress.value
}
}
}
func askProxyAddressAlert() {
let alert = UIAlertController(title: L10n.Accountpage.proxyAddressAlert,
message: nil,
preferredStyle: .alert)
let actionCancel = UIAlertAction(title: L10n.Actions.cancelAction,
style: .cancel) { [weak self] _ in
self?.viewModel.proxyEnabled.value = false
alert.dismiss(animated: true, completion: nil)
}
let actionConfirm = UIAlertAction(title: L10n.Accountpage.saveProxyAddress,
style: .default) { [weak self] _ in
if let textFields = alert.textFields, let text = textFields[0].text, !text.isEmpty {
self?.viewModel.changeProxyAvailability(enable: true, proxyAddress: text)
}
alert.dismiss(animated: false, completion: nil)
}
alert.addAction(actionCancel)
alert.addAction(actionConfirm)
alert.addTextField { [weak self] (textField) in
textField.placeholder = L10n.Accountpage.proxyPaceholder
textField.text = self?.viewModel.proxyAddress.value
}
if let textFields = alert.textFields {
textFields[0].rx.text.map({text in
if let text = text {
return !text.isEmpty
}
return false
}).bind(to: actionConfirm.rx.isEnabled).disposed(by: self.disposeBag)
}
self.present(alert, animated: true, completion: nil)
}
}
......
......@@ -39,6 +39,7 @@ enum SettingsSection: SectionModelType {
case blockedList
case sectionHeader(title: String)
case ordinary(label: String)
case notifications
}
var items: [SectionRow] {
......@@ -139,7 +140,7 @@ class MeViewModel: ViewModel, Stateable {
lazy var accountSettings: Observable<SettingsSection> = {
return Observable
.just(.accountSettings( items: [.sectionHeader(title: L10n.Accountpage.settingsHeader),
.blockedList, .proxy]))
.blockedList, .proxy, .notifications]))
}()
lazy var linkedDevices: Observable<SettingsSection> = {
......@@ -177,37 +178,139 @@ class MeViewModel: ViewModel, Stateable {
}
}()
lazy var proxyEnabled: Observable<Bool>? = {
required init (with injectionBag: InjectionBag) {
self.accountService = injectionBag.accountService
self.nameService = injectionBag.nameService
}
func linkDevice() {
self.stateSubject.onNext(MeState.linkNewDevice)
}
func showBlockedContacts() {
self.stateSubject.onNext(MeState.blockedContacts)
}
// MARK: - DHT Proxy
lazy var proxyEnabled: Variable<Bool> = {
if let account = self.accountService.currentAccount {
return self.accountService.proxyEnabled(accountID: account.id)
}
return nil
return Variable<Bool>(false)
}()
lazy var proxyInitialState: Bool = {
lazy var proxyAddress: Variable<String> = {
if let account = self.accountService.currentAccount {
return self.accountService.getCurrentProxyState(accountID: account.id)
return self.accountService.proxyAddress(accountID: account.id)
}
return false
return Variable<String>("")
}()
required init (with injectionBag: InjectionBag) {
self.accountService = injectionBag.accountService
self.nameService = injectionBag.nameService
}
lazy var proxyDisplaybele: Observable<String> = {
return Observable.combineLatest(self.proxyAddress.asObservable(),
self.proxyEnabled.asObservable()) { (address, proxy) in
if !proxy {
return ""
}
return address
func linkDevice() {
self.stateSubject.onNext(MeState.linkNewDevice)
}
}()
func changeProxyAvailability(enable: Bool, proxyAddress: String) {
guard let account = self.accountService.currentAccount else {
return
}
self.accountService.changeProxyAvailability(accountID: account.id, enable: enable, proxyAddress: proxyAddress)
}
func enableProxy(enable: Bool) {
func changeProxyAddress(address: String) {
guard let account = self.accountService.currentAccount else {
return
}
self.accountService.changeProxyAvailability(accountID: account.id, enable: enable)
self.accountService.updateProxyAddress(address: address, accountID: account.id)
}
func showBlockedContacts() {
self.stateSubject.onNext(MeState.blockedContacts)
// MARK: - Push Notifications
lazy var notificationsEnabled: Variable<Bool> = {
if let account = self.accountService.currentAccount {
return self.accountService.pushNotificationsEnabled(accountID: account.id)
}
return Variable<Bool>(false)
}()
func enablePushNotifications(enable: Bool) {
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)
}
// MARK: - Local Notifications
lazy var localNotificationsEnabled: Variable<Bool> = {
let variable = Variable<Bool>(LocalNotificationsHelper.isEnabled())
UserDefaults.standard.rx
.observe(Bool.self, enbleNotificationsKey)
.subscribe(onNext: { enable in
if let enable = enable {
variable.value = enable
}
}).disposed(by: self.disposeBag)
return variable
}()
func localNotifications(enable: Bool) {
let currentNotificationsState = LocalNotificationsHelper.isEnabled()
if enable == currentNotificationsState {return}
if !enable {
DispatchQueue.main.async { [weak self] in
self?.notificationsEnabled.value = currentNotificationsState
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(settingsUrl, completionHandler: nil)
} else {
UIApplication.shared.openURL(settingsUrl as URL)
}
}
}
} else {
self.enableLocalNotifications()
}
}
func enableLocalNotifications() {
if #available(iOS 10.0, *) {
let current = UNUserNotificationCenter.current()
current.getNotificationSettings(completionHandler: { [weak self] settings in
switch settings.authorizationStatus {
case .notDetermined:
break
case .denied:
DispatchQueue.main.async {
let enabled = LocalNotificationsHelper.isEnabled()
self?.notificationsEnabled.value = enabled
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, completionHandler: nil)
}
}
case .authorized:
break
}
})
} else {
if !UIApplication.shared.isRegisteredForRemoteNotifications {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: NotificationName.enablePushNotifications.rawValue), object: nil)
}
}
}
}
/*
* 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 NotificationCell: UITableViewCell, NibReusable {
@IBOutlet weak var enableNotificationsLabel: UILabel!
@IBOutlet weak var enableNotificationsSwitch: 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" id="KGk-i7-Jjw" customClass="NotificationCell" customModule="Ring" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="320" height="70"/>
<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="69.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Enable Push Notifications" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UJV-Wm-0vA">
<rect key="frame" x="16" y="24.5" width="195" 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="DTB-T2-7hR">
<rect key="frame" x="256" y="19.5" width="51" height="31"/>
</switch>
</subviews>
<constraints>
<constraint firstItem="UJV-Wm-0vA" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" id="339-cw-Cxc"/>
<constraint firstItem="UJV-Wm-0vA" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="4No-Id-ocd"/>
<constraint firstAttribute="trailing" secondItem="DTB-T2-7hR" secondAttribute="trailing" constant="15" id="mJK-li-C6U"/>
<constraint firstItem="DTB-T2-7hR" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="nIB-c4-E4y"/>
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<connections>
<outlet property="enableNotificationsLabel" destination="UJV-Wm-0vA" id="7c7-Gh-zmb"/>
<outlet property="enableNotificationsSwitch" destination="DTB-T2-7hR" id="BfI-ne-fUa"/>
</connections>
</tableViewCell>
</objects>
</document>
......@@ -26,6 +26,8 @@ class ProxyCell: UITableViewCell, NibReusable {
@IBOutlet weak var enableProxyLabel: UILabel!
@IBOutlet weak var switchProxy: UISwitch!
@IBOutlet weak var proxyAddrsss: UITextField!
@IBOutlet weak var proxyAddressContainer: UIView!
var disposeBag = DisposeBag()
......
This diff is collapsed.
......@@ -46,6 +46,8 @@ enum CallAcition: String {
}
}
let enbleNotificationsKey = "EnableUserNotifications"
class LocalNotificationsHelper {
let disposeBag = DisposeBag()
let callCategory = "CALL_CATEGORY"
......@@ -198,4 +200,12 @@ class LocalNotificationsHelper {
}).disposed(by: self.disposeBag)
}
}
class func isEnabled() ->