From e4a34b3ceb331c0952c2ad8c1abbd3d18550f246 Mon Sep 17 00:00:00 2001 From: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> Date: Thu, 23 Apr 2020 12:33:12 -0400 Subject: [PATCH] iOS: change minimum version to 11 - change minimum version - fix warnings Change-Id: I940f70056ac5fec72b82a047071f9eb54d6dc982 --- Ring/Ring.xcodeproj/project.pbxproj | 6 +- Ring/Ring/AppDelegate.swift | 197 +++++++----------- Ring/Ring/Bridging/Utils.mm | 2 +- Ring/Ring/Calls/CallViewModel.swift | 20 +- .../Conference/ContactPickerViewModel.swift | 6 +- .../views/ConferenceParticipantView.swift | 6 +- Ring/Ring/Constants/Generated/Images.swift | 2 +- Ring/Ring/Constants/Generated/Strings.swift | 7 +- .../Ring/Extensions/NSUserActivity+Call.swift | 1 - Ring/Ring/Extensions/UIView+Rx.swift | 2 +- .../Conversation/Cells/MessageCell.swift | 2 +- .../Cells/MessageCellDataTransferReceived.xib | 41 ++-- .../ConversationViewController.swift | 11 +- .../Conversation/ConversationViewModel.swift | 1 + .../ConversationsCoordinator.swift | 128 +++++------- .../SmartList/SmartlistViewController.swift | 12 +- .../SmartList/SmartlistViewModel.swift | 3 +- .../Features/Me/Me/BlockListViewModel.swift | 4 +- Ring/Ring/Features/Me/Me/MeViewModel.swift | 8 +- .../CreateProfileViewController.swift | 2 +- .../LinkToAccountManagerViewModel.swift | 9 +- .../Helpers/LocalNotificationsHelper.swift | 159 +++++--------- .../Protocols/ConversationNavigation.swift | 1 + Ring/Ring/Services/AccountsService.swift | 5 +- .../Ring/Services/CallsProviderDelegate.swift | 25 +-- Ring/Ring/Services/CallsService.swift | 2 +- Ring/Ring/Services/ConversationsManager.swift | 94 +++++---- Ring/Ring/Services/ConversationsService.swift | 1 + Ring/Ring/Services/VideoService.swift | 7 +- 29 files changed, 295 insertions(+), 469 deletions(-) diff --git a/Ring/Ring.xcodeproj/project.pbxproj b/Ring/Ring.xcodeproj/project.pbxproj index b8f45749d..4212b16df 100644 --- a/Ring/Ring.xcodeproj/project.pbxproj +++ b/Ring/Ring.xcodeproj/project.pbxproj @@ -2393,7 +2393,7 @@ "$(SRCROOT)/../../daemon/contrib/native-arm64/ffmpeg", ); INFOPLIST_FILE = Ring/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(SRCROOT)/../fat/lib"; MARKETING_VERSION = 2.47; @@ -2434,7 +2434,7 @@ "$(SRCROOT)/../../daemon/contrib/native-arm64/ffmpeg", ); INFOPLIST_FILE = Ring/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(SRCROOT)/../fat/lib"; MARKETING_VERSION = 2.47; @@ -2601,7 +2601,7 @@ "$(SRCROOT)/../../daemon/contrib/native-arm64/ffmpeg", ); INFOPLIST_FILE = Ring/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(SRCROOT)/../fat/lib"; MARKETING_VERSION = 2.47; diff --git a/Ring/Ring/AppDelegate.swift b/Ring/Ring/AppDelegate.swift index 0d6c74876..eb95b651e 100644 --- a/Ring/Ring/AppDelegate.swift +++ b/Ring/Ring/AppDelegate.swift @@ -28,7 +28,6 @@ import PushKit import ContactsUI // swiftlint:disable identifier_name -// swiftlint:disable type_body_length @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { var window: UIWindow? @@ -102,9 +101,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD self.window = UIWindow(frame: UIScreen.main.bounds) UserDefaults.standard.setValue(false, forKey: "_UIConstraintBasedLayoutLogUnsatisfiable") - if #available(iOS 10.0, *) { - UNUserNotificationCenter.current().delegate = self - } + UNUserNotificationCenter.current().delegate = self // initialize log format let console = ConsoleDestination() console.format = "$Dyyyy-MM-dd HH:mm:ss.SSS$d $C$L$c: $M" @@ -148,6 +145,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD self.window?.makeKeyAndVisible() prepareVideoAcceleration() + prepareAccounts() + self.voipRegistry.delegate = self + NotificationCenter.default.addObserver(self, selector: #selector(registerVoipNotifications), + name: NSNotification.Name(rawValue: NotificationName.enablePushNotifications.rawValue), + object: nil) + self.clearBadgeNumber() + return true + } + + func prepareAccounts() { self.accountService .needMigrateCurrentAccount .subscribe(onNext: { account in @@ -155,43 +162,37 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD self.appCoordinator.migrateAccount(accountId: account) } }).disposed(by: self.disposeBag) - self.accountService.initialAccountsLoading() .subscribe(onCompleted: { - //set selected account if exists - self.appCoordinator.start() - for account in self.accountService.accounts { - self.accountService.setDetails(forAccountId: account.id) - } - if self.accountService.hasAccountWithProxyEnabled() { - self.registerVoipNotifications() - } else { - self.unregisterVoipNotifications() - } - if let selectedAccountId = UserDefaults.standard.string(forKey: self.accountService.selectedAccountID), - let account = self.accountService.getAccount(fromAccountId: selectedAccountId) { + //set selected account if exists + self.appCoordinator.start() + for account in self.accountService.accounts { + self.accountService.setDetails(forAccountId: account.id) + } + if self.accountService.hasAccountWithProxyEnabled() { + self.registerVoipNotifications() + } else { + self.unregisterVoipNotifications() + } + if let selectedAccountId = UserDefaults.standard.string(forKey: self.accountService.selectedAccountID), + let account = self.accountService.getAccount(fromAccountId: selectedAccountId) { self.accountService.currentAccount = account - } - guard let currentAccount = self.accountService.currentAccount else { - self.log.error("Can't get current account!") - //if we don't have any account means it is first run, so enable hardware acceleration - self.videoService.setHardwareAccelerated(withState: true) - UserDefaults.standard.set(true, forKey: hardareAccelerationKey) - return - } - self.reloadDataFor(account: currentAccount) - if #available(iOS 10.0, *) { - return - } - // reimit new call signal to show incoming call alert - self.callService.checkForIncomingCall() - }, onError: { _ in - self.appCoordinator.showInitialLoading() - let time = DispatchTime.now() + 1 - DispatchQueue.main.asyncAfter(deadline: time) { - self.appCoordinator.showDatabaseError() - } - }).disposed(by: self.disposeBag) + } + guard let currentAccount = self.accountService.currentAccount else { + self.log.error("Can't get current account!") + //if we don't have any account means it is first run, so enable hardware acceleration + self.videoService.setHardwareAccelerated(withState: true) + UserDefaults.standard.set(true, forKey: hardareAccelerationKey) + return + } + self.reloadDataFor(account: currentAccount) + }, onError: { _ in + self.appCoordinator.showInitialLoading() + let time = DispatchTime.now() + 1 + DispatchQueue.main.asyncAfter(deadline: time) { + self.appCoordinator.showDatabaseError() + } + }).disposed(by: self.disposeBag) self.accountService.currentWillChange .subscribe(onNext: { account in @@ -204,12 +205,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD guard let currentAccount = account else {return} self.reloadDataFor(account: currentAccount) }).disposed(by: self.disposeBag) - self.voipRegistry.delegate = self - NotificationCenter.default.addObserver(self, selector: #selector(registerVoipNotifications), - name: NSNotification.Name(rawValue: NotificationName.enablePushNotifications.rawValue), - object: nil) - self.clearBadgeNumber() - return true } func reloadDataFor(account: AccountModel) { @@ -238,10 +233,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD func applicationDidBecomeActive(_ application: UIApplication) { self.clearBadgeNumber() - if #available(iOS 10.0, *) { - return - } - self.callService.checkForIncomingCall() } func prepareVideoAcceleration() { @@ -277,32 +268,23 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } } - // swiftlint:disable cyclomatic_complexity 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)} - case .provisional: - if !enabled { LocalNotificationsHelper.setNotification(enable: true)} - @unknown default: - break - } - }) - } else { - if UIApplication.shared.isRegisteredForRemoteNotifications { - if !enabled {LocalNotificationsHelper.setNotification(enable: true)} - } else { - if enabled {LocalNotificationsHelper.setNotification(enable: false)} + 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)} + case .provisional: + if !enabled { LocalNotificationsHelper.setNotification(enable: true)} + @unknown default: + break } - } + }) } @objc private func registerVoipNotifications() { @@ -320,45 +302,26 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD private func requestNotificationAuthorization() { let application = UIApplication.shared - if #available(iOS 10.0, *) { - 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) + 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) + } + }) } } private func clearBadgeNumber() { UIApplication.shared.applicationIconBadgeNumber = 0 - if #available(iOS 10.0, *) { - let center = UNUserNotificationCenter.current() - center.removeAllDeliveredNotifications() - center.removeAllPendingNotificationRequests() - } else { - UIApplication.shared.cancelAllLocalNotifications() - } + let center = UNUserNotificationCenter.current() + center.removeAllDeliveredNotifications() + center.removeAllPendingNotificationRequests() } - @available(iOS 10.0, *) func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let data = response.notification.request.content.userInfo self.handleNotificationActions(data: data, responseIdentifier: response.actionIdentifier) @@ -399,23 +362,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } } - func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, completionHandler: @escaping () -> Void) { - if let identifier = identifier, let data = notification.userInfo { - self.handleNotificationActions(data: data, responseIdentifier: identifier) - } - 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 findContactAndStartCall(hash: String, isVideo: Bool) { //if saved jami hash if hash.isSHA1() { @@ -476,14 +422,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { - if #available(iOS 10.0, *) { - guard let handle = userActivity.startCallHandle else { - return false - } - self.findContactAndStartCall(hash: handle.hash, isVideo: handle.isVideo) - return true + guard let handle = userActivity.startCallHandle else { + return false } - return false + self.findContactAndStartCall(hash: handle.hash, isVideo: handle.isVideo) + return true } } diff --git a/Ring/Ring/Bridging/Utils.mm b/Ring/Ring/Bridging/Utils.mm index 4278357bd..db9e45bfa 100644 --- a/Ring/Ring/Bridging/Utils.mm +++ b/Ring/Ring/Bridging/Utils.mm @@ -170,7 +170,7 @@ extern "C" { auto ciImageOrientation = [Utils ciimageOrientationFromRotation:rotation]; if (@available(iOS 11.0, *)) { image = [image imageByApplyingCGOrientation: ciImageOrientation]; - } else if (@available(iOS 10.0, *)) { + } else { image = [image imageByApplyingOrientation:static_cast<int>(ciImageOrientation)]; } UIImage * imageUI = [UIImage imageWithCIImage:image scale:1 orientation: uiImageOrientation]; diff --git a/Ring/Ring/Calls/CallViewModel.swift b/Ring/Ring/Calls/CallViewModel.swift index ff534c8d2..4c3521bbf 100644 --- a/Ring/Ring/Calls/CallViewModel.swift +++ b/Ring/Ring/Calls/CallViewModel.swift @@ -173,18 +173,14 @@ class CallViewModel: Stateable, ViewModel { if anotherCall.participantsCallId.count == 1 { self?.rendererId = anotherCallid } - if #available(iOS 10.0, *) { - self?.callsProvider.stopCall(callUUID: call.callUUID) - } + self?.callsProvider.stopCall(callUUID: call.callUUID) return !hide } } if hide { self?.videoService.setCameraOrientation(orientation: UIDevice.current.orientation) self?.videoService.restoreStateAfterconference() - if #available(iOS 10.0, *) { - self?.callsProvider.stopCall(callUUID: call.callUUID) - } + self?.callsProvider.stopCall(callUUID: call.callUUID) } return hide }) @@ -229,9 +225,9 @@ class CallViewModel: Stateable, ViewModel { lazy var bottomInfo: Observable<String> = { return currentCall .startWith(self.call ?? CallModel()) - .filter({ [weak self] call in + .filter({call in return call.callType == .outgoing - }).map({ [weak self] call in + }).map({call in switch call.state { case .connecting : return L10n.Calls.connecting @@ -429,7 +425,7 @@ class CallViewModel: Stateable, ViewModel { guard let call = self.call else { return } - if #available(iOS 10.0, *), stopProvider { + if stopProvider { self.callsProvider.stopCall(callUUID: call.callUUID) call.participantsCallId.forEach { (callId) in if let participantCall = self.callService.call(callID: callId) { @@ -471,10 +467,8 @@ class CallViewModel: Stateable, ViewModel { .subscribe(onSuccess: { [weak self] callModel in callModel.callUUID = UUID() self?.call = callModel - if #available(iOS 10.0, *) { - self?.callsProvider - .startCall(account: account, call: callModel) - } + self?.callsProvider + .startCall(account: account, call: callModel) }).disposed(by: self.disposeBag) } diff --git a/Ring/Ring/Calls/Conference/ContactPickerViewModel.swift b/Ring/Ring/Calls/Conference/ContactPickerViewModel.swift index b7471de24..1ce652a15 100644 --- a/Ring/Ring/Calls/Conference/ContactPickerViewModel.swift +++ b/Ring/Ring/Calls/Conference/ContactPickerViewModel.swift @@ -126,7 +126,11 @@ class ContactPickerViewModel: Stateable, ViewModel { let newContacts = item.contacts.filter { contact in var mutableContact = contact let searchLowercased = search.lowercased() - return mutableContact.firstLine.lowercased().contains(searchLowercased) || mutableContact.secondLine.lowercased().contains(searchLowercased) || mutableContact.hash.lowercased().contains(searchLowercased) + return mutableContact.firstLine.lowercased().contains(searchLowercased) || + mutableContact.secondLine.lowercased() + .contains(searchLowercased) || + mutableContact.hash.lowercased() + .contains(searchLowercased) } mutabeItem.contacts = newContacts return mutabeItem diff --git a/Ring/Ring/Calls/views/ConferenceParticipantView.swift b/Ring/Ring/Calls/views/ConferenceParticipantView.swift index fe130b3d1..7c3130c16 100644 --- a/Ring/Ring/Calls/views/ConferenceParticipantView.swift +++ b/Ring/Ring/Calls/views/ConferenceParticipantView.swift @@ -64,11 +64,7 @@ class ConferenceParticipantView: UIView { label.text = L10n.Calls.haghUp label.textAlignment = .center let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: menuWidth, height: menuHight)) - if #available(iOS 10.0, *) { - label.adjustsFontSizeToFitWidth = true - } else { - label.font = UIFont.systemFont(ofSize: 10) - } + label.adjustsFontSizeToFitWidth = true menu.cornerRadius = 10 menu.addSubview(background) menu.addSubview(label) diff --git a/Ring/Ring/Constants/Generated/Images.swift b/Ring/Ring/Constants/Generated/Images.swift index 6b001a97e..1fdfba0aa 100644 --- a/Ring/Ring/Constants/Generated/Images.swift +++ b/Ring/Ring/Constants/Generated/Images.swift @@ -1,5 +1,5 @@ // swiftlint:disable all -// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen +// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen #if os(OSX) import AppKit.NSImage diff --git a/Ring/Ring/Constants/Generated/Strings.swift b/Ring/Ring/Constants/Generated/Strings.swift index 41fc2e71b..14f5e5308 100644 --- a/Ring/Ring/Constants/Generated/Strings.swift +++ b/Ring/Ring/Constants/Generated/Strings.swift @@ -1,5 +1,5 @@ // swiftlint:disable all -// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen +// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen import Foundation @@ -19,6 +19,8 @@ internal enum L10n { internal static let createSipAccount = L10n.tr("Localizable", "account.createSipAccount") /// Enable Account internal static let enableAccount = L10n.tr("Localizable", "account.enableAccount") + /// account need to be migrated + internal static let needMigration = L10n.tr("Localizable", "account.needMigration") /// Enter Password internal static let passwordLabel = L10n.tr("Localizable", "account.passwordLabel") /// Port @@ -505,6 +507,8 @@ internal enum L10n { } internal enum Welcome { + /// Connect to account manager + internal static let connectToManager = L10n.tr("Localizable", "welcome.connectToManager") /// Create a Jami account internal static let createAccount = L10n.tr("Localizable", "welcome.createAccount") /// Link this device to an account @@ -522,6 +526,7 @@ internal enum L10n { extension L10n { fileprivate static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { + // swiftlint:disable:next nslocalizedstring_key let format = NSLocalizedString(key, tableName: table, bundle: Bundle(for: BundleToken.self), comment: "") return String(format: format, locale: Locale.current, arguments: args) } diff --git a/Ring/Ring/Extensions/NSUserActivity+Call.swift b/Ring/Ring/Extensions/NSUserActivity+Call.swift index a742078f9..b1308c861 100644 --- a/Ring/Ring/Extensions/NSUserActivity+Call.swift +++ b/Ring/Ring/Extensions/NSUserActivity+Call.swift @@ -20,7 +20,6 @@ import Foundation import Intents -@available(iOS 10.0, *) extension NSUserActivity { var startCallHandle: (hash: String, isVideo: Bool)? { guard let interaction = interaction else { return nil } diff --git a/Ring/Ring/Extensions/UIView+Rx.swift b/Ring/Ring/Extensions/UIView+Rx.swift index 3e181fcbc..1dc4c2cfa 100644 --- a/Ring/Ring/Extensions/UIView+Rx.swift +++ b/Ring/Ring/Extensions/UIView+Rx.swift @@ -26,7 +26,7 @@ extension Reactive where Base: UIView { //show view with animation and hide without public var isVisible: AnyObserver<Bool> { - return Binder (self.base) { view, hidden in + return Binder(self.base) { view, hidden in if hidden == true { view.isHidden = true view.alpha = 0 diff --git a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift index 477be4390..5a2df23db 100644 --- a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift +++ b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift @@ -237,7 +237,7 @@ class MessageCell: UITableViewCell, NibReusable, PlayerDelegate { self.messageLabel.handleURLTap { url in let urlString = url.absoluteString if let prefixedUrl = URL(string: urlString.contains("http") ? urlString : "http://\(urlString)") { - UIApplication.shared.openURL(prefixedUrl) + UIApplication.shared.open(prefixedUrl, completionHandler: nil) } } } diff --git a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCellDataTransferReceived.xib b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCellDataTransferReceived.xib index a5e9a6b2b..aace96e4b 100644 --- a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCellDataTransferReceived.xib +++ b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCellDataTransferReceived.xib @@ -1,13 +1,9 @@ <?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> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> + <device id="retina4_7" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/> - <capability name="Constraints to layout margins" minToolsVersion="6.0"/> - <capability name="Unknown constraint types" minToolsVersion="5.1"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> @@ -17,11 +13,11 @@ <rect key="frame" x="0.0" y="0.0" width="510" height="110"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="52M-1g-koJ" id="a8Q-63-e84"> - <rect key="frame" x="0.0" y="0.0" width="510" height="109.5"/> + <rect key="frame" x="0.0" y="0.0" width="510" height="110"/> <autoresizingMask key="autoresizingMask"/> <subviews> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="PUF-dd-SHE" userLabel="Avatar View"> - <rect key="frame" x="16" y="67" width="32" height="32"/> + <rect key="frame" x="16" y="68" width="32" height="32"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <constraints> <constraint firstAttribute="height" constant="32" id="2Sx-kt-bxB"/> @@ -29,7 +25,7 @@ </constraints> </view> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Mcd-XM-6nW" userLabel="Top Corner"> - <rect key="frame" x="64" y="8.5" width="17" height="17"/> + <rect key="frame" x="64" y="8" width="17" height="17"/> <color key="backgroundColor" red="1" green="0.0" blue="1" alpha="1" colorSpace="calibratedRGB"/> <constraints> <constraint firstAttribute="width" constant="17" id="ByW-4A-Bl3"/> @@ -45,7 +41,7 @@ </constraints> </view> <view clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="k7r-gv-wn2" customClass="MessageBubble" customModule="Ring" customModuleProvider="target"> - <rect key="frame" x="64" y="8.5" width="382" height="93"/> + <rect key="frame" x="64" y="8" width="382" height="94"/> <subviews> <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="attachment_icon" translatesAutoresizingMaskIntoConstraints="NO" id="Vif-9c-Vza" userLabel="File Icon"> <rect key="frame" x="14" y="7" width="24" height="24"/> @@ -64,7 +60,7 @@ <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="748" text="42KB" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZGC-d7-MmV" userLabel="Size Label" customClass="ActiveLabel" customModule="ActiveLabel"> - <rect key="frame" x="14" y="35" width="37" height="17.5"/> + <rect key="frame" x="14" y="35" width="37" height="18"/> <constraints> <constraint firstAttribute="height" constant="18" id="13y-MF-2dV"/> </constraints> @@ -73,7 +69,7 @@ <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="748" text="50%" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QMh-zf-aOl" userLabel="Status Label" customClass="ActiveLabel" customModule="ActiveLabel"> - <rect key="frame" x="336" y="34.5" width="30" height="18"/> + <rect key="frame" x="335.5" y="35" width="30.5" height="18"/> <constraints> <constraint firstAttribute="height" constant="18" id="rfB-KZ-aJN"/> </constraints> @@ -82,22 +78,22 @@ <nil key="highlightedColor"/> </label> <progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="753" verticalCompressionResistancePriority="751" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="tc3-3o-eIM"> - <rect key="frame" x="16" y="56.5" width="350" height="2"/> + <rect key="frame" x="16" y="57" width="350" height="2"/> <constraints> <constraint firstAttribute="height" constant="2" id="9an-z7-YYj"/> </constraints> </progressView> <stackView opaque="NO" contentMode="scaleToFill" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="dFz-uY-Lik" userLabel="Buttons"> - <rect key="frame" x="14" y="62.5" width="177" height="24"/> + <rect key="frame" x="14" y="63" width="174.5" height="24"/> <subviews> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ufs-kC-RwY" userLabel="Accept Button"> - <rect key="frame" x="0.0" y="0.0" width="81" height="24"/> + <rect key="frame" x="0.0" y="0.0" width="78.5" height="24"/> <state key="normal" title="Accept" image="download_icon"> <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> </state> </button> <button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="752" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KIE-mj-gUg" userLabel="Cancel Button"> - <rect key="frame" x="97" y="0.0" width="80" height="24"/> + <rect key="frame" x="94.5" y="0.0" width="80" height="24"/> <state key="normal" title="Refuse" image="close_icon"> <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> </state> @@ -108,7 +104,7 @@ </constraints> </stackView> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LoC-UA-VKl"> - <rect key="frame" x="0.0" y="0.0" width="382" height="93"/> + <rect key="frame" x="0.0" y="0.0" width="382" height="94"/> </view> </subviews> <color key="backgroundColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="calibratedRGB"/> @@ -134,7 +130,6 @@ <constraint firstAttribute="bottom" secondItem="dFz-uY-Lik" secondAttribute="bottom" constant="7" id="uMF-UH-lRt"/> <constraint firstAttribute="bottom" secondItem="LoC-UA-VKl" secondAttribute="bottom" id="xqJ-Kf-sFD"/> <constraint firstItem="Vif-9c-Vza" firstAttribute="leading" secondItem="k7r-gv-wn2" secondAttribute="leading" constant="14" id="ziG-Bm-awa"/> - <constraint firstAttribute="top" secondItem="k7r-gv-wn2" secondAttribute="top" id="zsT-GC-e5W"/> </constraints> <userDefinedRuntimeAttributes> <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius"> @@ -143,21 +138,21 @@ </userDefinedRuntimeAttributes> </view> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WB7-Io-YuE" userLabel="Left Divider"> - <rect key="frame" x="36" y="19.5" width="126.5" height="1"/> + <rect key="frame" x="31" y="19" width="131" height="1"/> <color key="backgroundColor" red="0.94117647059999998" green="0.94117647059999998" blue="0.94117647059999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstAttribute="height" constant="1" id="AlE-Y2-o9R"/> </constraints> </view> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tI0-XY-IEm" userLabel="Right Divider"> - <rect key="frame" x="348.5" y="19.5" width="125.5" height="1"/> + <rect key="frame" x="348" y="19" width="131" height="1"/> <color key="backgroundColor" red="0.94117647059999998" green="0.94117647059999998" blue="0.94117647059999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstAttribute="height" constant="1" id="vAB-5v-8HU"/> </constraints> </view> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="11/14/2016 12:34PM" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lC1-z1-ZwQ" userLabel="Message Time"> - <rect key="frame" x="178.5" y="9" width="154" height="20.5"/> + <rect key="frame" x="178" y="9" width="154" height="20.5"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <fontDescription key="fontDescription" type="system" pointSize="17"/> <nil key="textColor"/> @@ -213,6 +208,6 @@ <resources> <image name="attachment_icon" width="24" height="24"/> <image name="close_icon" width="24" height="24"/> - <image name="download_icon" width="24" height="24"/> + <image name="download_icon" width="21.5" height="21.5"/> </resources> </document> diff --git a/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift b/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift index c7ade02ca..5ed4bd4d6 100644 --- a/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift +++ b/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift @@ -311,11 +311,8 @@ class ConversationViewController: UIViewController, self.viewModel.sendAndSaveFile(displayName: imageFileName, imageData: imageData) } else if picker.sourceType == UIImagePickerController.SourceType.photoLibrary { // image from library - guard let imageURL = info[UIImagePickerController.InfoKey.referenceURL] as? URL else { return } - self.log.debug("imageURL: \(String(describing: imageURL))") - - let result = PHAsset.fetchAssets(withALAssetURLs: [imageURL], options: nil) - var imageFileName = result.firstObject?.value(forKey: "filename") as? String ?? "Unknown" + guard let phAsset = info[UIImagePickerController.InfoKey.phAsset] as? PHAsset else { return } + var imageFileName = phAsset.value(forKey: "filename") as? String ?? "Unknown" // seems that HEIC, HEIF, and JPG files in the iOS photo library start with 0x89 0x50 (png) // so funky cold medina @@ -331,8 +328,6 @@ class ConversationViewController: UIViewController, } self.log.debug("localCachePath: \(String(describing: localCachePath))") - guard let phAsset = result.firstObject else { return } - if phAsset.mediaType == .image { if let img = info[.editedImage] as? UIImage { image = img @@ -343,7 +338,7 @@ class ConversationViewController: UIViewController, copyImageToCache(image: image, imagePath: localCachePath.path) self.viewModel.sendFile(filePath: localCachePath.path, displayName: imageFileName, - localIdentifier: result.firstObject?.localIdentifier) + localIdentifier: phAsset.localIdentifier) } else if phAsset.mediaType == .video { PHImageManager.default().requestAVAsset(forVideo: phAsset, options: PHVideoRequestOptions(), diff --git a/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift b/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift index 3c23dad2a..0e3668305 100644 --- a/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift +++ b/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift @@ -26,6 +26,7 @@ import RxSwift import SwiftyBeaver // swiftlint:disable type_body_length +// swiftlint:disable file_length class ConversationViewModel: Stateable, ViewModel { /** diff --git a/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift b/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift index 86c9629b3..ff120c130 100644 --- a/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift +++ b/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift @@ -91,12 +91,7 @@ class ConversationsCoordinator: Coordinator, StateableResponsive, ConversationNa }).disposed(by: self.disposeBag) } - /* - * when receive a new call trigger CallKit for iOS 10 and than navigate to - * call controller when call accepted. For iOS less than 10 present - * call controller or trigger notifications, depending of current app state - */ - // swiftlint:enable cyclomatic_complexity + // swiftlint:disable cyclomatic_complexity func showIncomingCall(call: CallModel) { guard let account = self.accountService .getAccount(fromAccountId: call.accountId), @@ -110,84 +105,59 @@ class ConversationsCoordinator: Coordinator, StateableResponsive, ConversationNa callViewController.viewModel.call = call var tempBag = DisposeBag() - if #available(iOS 10.0, *) { - call.callUUID = UUID() - callsProvider - .reportIncomingCall(account: account, call: call) { _ in - // if starting CallKit failed fallback to jami call screen - if UIApplication.shared.applicationState != .active { - if AccountModelHelper - .init(withAccount: account).isAccountSip() || - !self.accountService.getCurrentProxyState(accountID: account.id) { - return - } - self.triggerCallNotifications(call: call) + call.callUUID = UUID() + callsProvider + .reportIncomingCall(account: account, call: call) { _ in + // if starting CallKit failed fallback to jami call screen + if UIApplication.shared.applicationState != .active { + if AccountModelHelper + .init(withAccount: account).isAccountSip() || + !self.accountService.getCurrentProxyState(accountID: account.id) { return } - if account.id != call.accountId { - self.accountService.currentAccount = self.accountService.getAccount(fromAccountId: call.accountId) - } - topController.dismiss(animated: false, completion: nil) - guard let parent = self.parentCoordinator as? AppCoordinator else {return} - parent.openConversation(participantID: call.participantUri) - self.present(viewController: callViewController, - withStyle: .appear, - withAnimation: false, - withStateable: callViewController.viewModel) - } - callsProvider.sharedResponseStream - .filter({ serviceEvent in - if serviceEvent.eventType != ServiceEventType.callProviderAnswerCall { - return false - } - guard let callUUID: String = serviceEvent - .getEventInput(ServiceEventInput.callUUID) else {return false} - return callUUID == call.callUUID.uuidString - }).subscribe(onNext: { _ in - self.navigationViewController.popToRootViewController(animated: false) - if account.id != call.accountId { - self.accountService.currentAccount = self.accountService.getAccount(fromAccountId: call.accountId) - } - topController.dismiss(animated: false, completion: nil) - guard let parent = self.parentCoordinator as? AppCoordinator else {return} - parent.openConversation(participantID: call.participantUri) - self.present(viewController: callViewController, - withStyle: .appear, - withAnimation: false, - withStateable: callViewController.viewModel) - tempBag = DisposeBag() - }).disposed(by: tempBag) - callViewController.viewModel.dismisVC - .share() - .subscribe(onNext: { hide in - if hide { - tempBag = DisposeBag() - } - }).disposed(by: tempBag) - - } else { - if UIApplication.shared.applicationState != .active { - if AccountModelHelper - .init(withAccount: account).isAccountSip() || - !self.accountService.getCurrentProxyState(accountID: account.id) { + self.triggerCallNotifications(call: call) return } - triggerCallNotifications(call: call) - return - } - if account.id != call.accountId { - self.accountService.currentAccount = self.accountService.getAccount(fromAccountId: call.accountId) - } - - self.injectionBag.audioService.setToRing() - topController.dismiss(animated: false, completion: nil) - guard let parent = self.parentCoordinator as? AppCoordinator else {return} - parent.openConversation(participantID: call.participantUri) - self.present(viewController: callViewController, - withStyle: .appear, - withAnimation: false, - withStateable: callViewController.viewModel) + if account.id != call.accountId { + self.accountService.currentAccount = self.accountService.getAccount(fromAccountId: call.accountId) + } + topController.dismiss(animated: false, completion: nil) + guard let parent = self.parentCoordinator as? AppCoordinator else {return} + parent.openConversation(participantID: call.participantUri) + self.present(viewController: callViewController, + withStyle: .appear, + withAnimation: false, + withStateable: callViewController.viewModel) } + callsProvider.sharedResponseStream + .filter({ serviceEvent in + if serviceEvent.eventType != ServiceEventType.callProviderAnswerCall { + return false + } + guard let callUUID: String = serviceEvent + .getEventInput(ServiceEventInput.callUUID) else {return false} + return callUUID == call.callUUID.uuidString + }).subscribe(onNext: { _ in + self.navigationViewController.popToRootViewController(animated: false) + if account.id != call.accountId { + self.accountService.currentAccount = self.accountService.getAccount(fromAccountId: call.accountId) + } + topController.dismiss(animated: false, completion: nil) + guard let parent = self.parentCoordinator as? AppCoordinator else {return} + parent.openConversation(participantID: call.participantUri) + self.present(viewController: callViewController, + withStyle: .appear, + withAnimation: false, + withStateable: callViewController.viewModel) + tempBag = DisposeBag() + }).disposed(by: tempBag) + callViewController.viewModel.dismisVC + .share() + .subscribe(onNext: { hide in + if hide { + tempBag = DisposeBag() + } + }).disposed(by: tempBag) } func createNewAccount() { diff --git a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift index f00247f6e..f0c465a82 100644 --- a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift +++ b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift @@ -149,11 +149,7 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased self.settingsButton.backgroundColor = nil self.settingsButton.rx.tap.subscribe(onNext: { _ in if let url = URL(string: UIApplication.openSettingsURLString) { - if #available(iOS 10.0, *) { - UIApplication.shared.open(url, completionHandler: nil) - } else { - UIApplication.shared.openURL(url) - } + UIApplication.shared.open(url, completionHandler: nil) } }).disposed(by: self.disposeBag) @@ -221,14 +217,12 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased accountButtonItem .customView? .translatesAutoresizingMaskIntoConstraints = false - if #available(iOS 10.0, *) { - accountButtonItem.customView? + accountButtonItem.customView? .heightAnchor .constraint(equalToConstant: size).isActive = true - accountButtonItem.customView? + accountButtonItem.customView? .widthAnchor .constraint(equalToConstant: 80).isActive = true - } accountButton.rx.tap .throttle(0.5, scheduler: MainScheduler.instance) .subscribe(onNext: { [weak self] in diff --git a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift index 23fdeff10..f25fd8412 100644 --- a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift +++ b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift @@ -24,7 +24,6 @@ import RxSwift import SwiftyBeaver -// swiftlint:disable type_body_length class SmartlistViewModel: Stateable, ViewModel { private let log = SwiftyBeaver.self @@ -419,7 +418,7 @@ class SmartlistViewModel: Stateable, ViewModel { func changeCurrentAccount(accountId: String) { if let account = self.accountsService.getAccount(fromAccountId: accountId) { - if (accountsService.needAccountMigration(accountId: accountId)) { + if accountsService.needAccountMigration(accountId: accountId) { self.stateSubject.onNext(ConversationState.needAccountMigration(accountId: accountId)) return } diff --git a/Ring/Ring/Features/Me/Me/BlockListViewModel.swift b/Ring/Ring/Features/Me/Me/BlockListViewModel.swift index 8355d6f24..edd2cd9b9 100644 --- a/Ring/Ring/Features/Me/Me/BlockListViewModel.swift +++ b/Ring/Ring/Features/Me/Me/BlockListViewModel.swift @@ -36,7 +36,7 @@ class BlockListViewModel: ViewModel { return self.contacts.asObservable().map({ [weak self] contacts in var bannedItems = [BannedContactItem]() _ = contacts.filter {contact in contact.banned} - .map ({ contact in + .map({ contact in let items = self?.initialItems.filter({ item in return item.contact.hash == contact.hash }) @@ -89,7 +89,7 @@ class BlockListViewModel: ViewModel { return lookupNameResponse.address != nil && lookupNameResponse.address == contact.hash }) - .subscribe(onNext: { [weak self] lookupNameResponse in + .subscribe(onNext: {lookupNameResponse in if let name = lookupNameResponse.name, !name.isEmpty { contact.userName = name } diff --git a/Ring/Ring/Features/Me/Me/MeViewModel.swift b/Ring/Ring/Features/Me/Me/MeViewModel.swift index 0797409c7..fdea56e2c 100644 --- a/Ring/Ring/Features/Me/Me/MeViewModel.swift +++ b/Ring/Ring/Features/Me/Me/MeViewModel.swift @@ -534,7 +534,7 @@ class MeViewModel: ViewModel, Stateable { rows = [.device(device: devices[0])] for deviceIndex in 1 ..< devices.count { let device = devices[deviceIndex] - rows!.append (.device(device: device)) + rows!.append(.device(device: device)) } } else if let account = self.accountService.currentAccount, let details = account.details { @@ -620,11 +620,7 @@ class MeViewModel: ViewModel, Stateable { // if notiications not allowed open application settings if enable == true && enable != notificationsPermitted.value { if let url = URL(string: UIApplication.openSettingsURLString) { - if #available(iOS 10.0, *) { - UIApplication.shared.open(url, completionHandler: nil) - } else { - UIApplication.shared.openURL(url) - } + UIApplication.shared.open(url, completionHandler: nil) } } } diff --git a/Ring/Ring/Features/Walkthrough/CreateProfile/CreateProfileViewController.swift b/Ring/Ring/Features/Walkthrough/CreateProfile/CreateProfileViewController.swift index 7eef28564..bea499aa6 100644 --- a/Ring/Ring/Features/Walkthrough/CreateProfile/CreateProfileViewController.swift +++ b/Ring/Ring/Features/Walkthrough/CreateProfile/CreateProfileViewController.swift @@ -204,7 +204,7 @@ class CreateProfileViewController: EditProfileViewController, StoryboardBased, V override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - self.navigationItem.setHidesBackButton(true, animated: true); + self.navigationItem.setHidesBackButton(true, animated: true) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear(withNotification:)), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear(withNotification:)), name: UIResponder.keyboardWillHideNotification, object: nil) } diff --git a/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewModel.swift b/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewModel.swift index 569a69d3e..9e088489c 100644 --- a/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewModel.swift +++ b/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewModel.swift @@ -40,10 +40,11 @@ class LinkToAccountManagerViewModel: Stateable, ViewModel { }() lazy var canLink: Observable<Bool> = { - return Observable.combineLatest(self.userName.asObservable(), - self.password.asObservable(), - self.manager.asObservable(), - self.createState) {( name: String,password: String, manager: String, state: AccountCreationState) -> Bool in + return Observable + .combineLatest(self.userName.asObservable(), + self.password.asObservable(), + self.manager.asObservable(), + self.createState) {( name: String, password: String, manager: String, state: AccountCreationState) -> Bool in return !name.isEmpty && !password.isEmpty && !manager.isEmpty && !state.isInProgress } }() diff --git a/Ring/Ring/Helpers/LocalNotificationsHelper.swift b/Ring/Ring/Helpers/LocalNotificationsHelper.swift index 5b3baf327..8d867c7e1 100644 --- a/Ring/Ring/Helpers/LocalNotificationsHelper.swift +++ b/Ring/Ring/Helpers/LocalNotificationsHelper.swift @@ -73,71 +73,34 @@ class LocalNotificationsHelper { let body = data [NotificationUserInfoKeys.messageContent.rawValue] else { return } - if #available(iOS 10.0, *) { - let content = UNMutableNotificationContent() - content.title = title - content.body = body - content.userInfo = data - content.sound = UNNotificationSound.default - content.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber - let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false) - let identifier = Int64(arc4random_uniform(10000000)) - let notificationRequest = UNNotificationRequest(identifier: "\(identifier)", content: content, trigger: notificationTrigger) - UNUserNotificationCenter.current().add(notificationRequest) { (error) in - if let error = error { - print("Unable to Add Notification Request (\(error), \(error.localizedDescription))") - } + let content = UNMutableNotificationContent() + content.title = title + content.body = body + content.userInfo = data + content.sound = UNNotificationSound.default + content.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber + let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false) + let identifier = Int64(arc4random_uniform(10000000)) + let notificationRequest = UNNotificationRequest(identifier: "\(identifier)", content: content, trigger: notificationTrigger) + UNUserNotificationCenter.current().add(notificationRequest) { (error) in + if let error = error { + print("Unable to Add Notification Request (\(error), \(error.localizedDescription))") } - } else { - let notification = UILocalNotification() - notification.alertTitle = title - notification.alertBody = body - notification.userInfo = data - notification.soundName = UILocalNotificationDefaultSoundName - notification.applicationIconBadgeNumber = UIApplication.shared.applicationIconBadgeNumber + 1 - UIApplication.shared.scheduleLocalNotification(notification) } } func createCallCategory() { - if #available(iOS 10.0, *) { - let acceptAction = UNNotificationAction(identifier: CallAcition.accept.rawValue, - title: CallAcition.accept.title(), - options: [.foreground]) - let refuseAction = UNNotificationAction(identifier: CallAcition.refuse.rawValue, - title: CallAcition.refuse.title(), - options: []) + let acceptAction = UNNotificationAction(identifier: CallAcition.accept.rawValue, + title: CallAcition.accept.title(), + options: [.foreground]) + let refuseAction = UNNotificationAction(identifier: CallAcition.refuse.rawValue, + title: CallAcition.refuse.title(), + options: []) - let callCategory = UNNotificationCategory(identifier: self.callCategory, - actions: [acceptAction, refuseAction], - intentIdentifiers: [], options: []) - UNUserNotificationCenter.current().setNotificationCategories([callCategory]) - } else { - guard let notificationTypes: UIUserNotificationType = (UIApplication.shared.currentUserNotificationSettings?.types) else { - return - } - let acceptAction = UIMutableUserNotificationAction() - acceptAction.identifier = CallAcition.accept.rawValue - acceptAction.title = CallAcition.accept.title() - acceptAction.activationMode = UIUserNotificationActivationMode.foreground - let refuseAction = UIMutableUserNotificationAction() - refuseAction.identifier = CallAcition.refuse.rawValue - refuseAction.title = CallAcition.refuse.title() - refuseAction.activationMode = UIUserNotificationActivationMode.background - let callCategory = UIMutableUserNotificationCategory() - callCategory.identifier = self.callCategory - // A. Set actions for the default context - callCategory.setActions([acceptAction, refuseAction], - for: UIUserNotificationActionContext.default) - // B. Set actions for the minimal context - callCategory.setActions([acceptAction, refuseAction], - for: UIUserNotificationActionContext.minimal) - guard let categoriesForSettings: Set<UIUserNotificationCategory> = NSSet(objects: callCategory) as? Set<UIUserNotificationCategory> else { - return - } - let newNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: categoriesForSettings) - UIApplication.shared.registerUserNotificationSettings(newNotificationSettings) - } + let callCategory = UNNotificationCategory(identifier: self.callCategory, + actions: [acceptAction, refuseAction], + intentIdentifiers: [], options: []) + UNUserNotificationCenter.current().setNotificationCategories([callCategory]) } @objc func cancelCall(timer: Timer) { @@ -165,58 +128,36 @@ class LocalNotificationsHelper { selector: #selector(cancelCall), userInfo: [NotificationUserInfoKeys.callID.rawValue: callID], repeats: false) - if #available(iOS 10.0, *) { - let content = UNMutableNotificationContent() - content.title = title - content.body = name - content.userInfo = data - content.categoryIdentifier = self.callCategory - let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false) - let notificationRequest = UNNotificationRequest(identifier: callID, content: content, trigger: notificationTrigger) - UNUserNotificationCenter.current().add(notificationRequest) { (error) in - if let error = error { - print("Unable to Add Notification Request (\(error), \(error.localizedDescription))") - } + let content = UNMutableNotificationContent() + content.title = title + content.body = name + content.userInfo = data + content.categoryIdentifier = self.callCategory + let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false) + let notificationRequest = UNNotificationRequest(identifier: callID, content: content, trigger: notificationTrigger) + UNUserNotificationCenter.current().add(notificationRequest) { (error) in + if let error = error { + print("Unable to Add Notification Request (\(error), \(error.localizedDescription))") } - callService.currentCall(callId: callID).filter({ call in - return (call.state == .over || call.state == .failure) - }).single() - .observeOn(MainScheduler.instance) - .subscribe(onNext: { _ in - let content = UNMutableNotificationContent() - content.title = NotificationCallTitle.missedCall.getString() - content.body = name - content.sound = UNNotificationSound.default - content.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber - let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false) - let notificationRequest = UNNotificationRequest(identifier: callID, content: content, trigger: notificationTrigger) - UNUserNotificationCenter.current().add(notificationRequest) { (error) in - if let error = error { - print("Unable to Add Notification Request (\(error), \(error.localizedDescription))") - } - } - }).disposed(by: self.disposeBag) - } else { - let notification = UILocalNotification() - notification.userInfo = data - notification.alertTitle = title - notification.alertBody = name - notification.category = self.callCategory - notification.applicationIconBadgeNumber = UIApplication.shared.applicationIconBadgeNumber + 1 - UIApplication.shared.scheduleLocalNotification(notification) - callService.currentCall(callId: callID).filter({ call in - return (call.state == .over || call.state == .failure) - }).single() - .subscribe(onNext: { _ in - let notification = UILocalNotification() - notification.userInfo = data - notification.alertTitle = NotificationCallTitle.missedCall.getString() - notification.alertBody = name - notification.soundName = UILocalNotificationDefaultSoundName - notification.applicationIconBadgeNumber = UIApplication.shared.applicationIconBadgeNumber + 1 - UIApplication.shared.scheduleLocalNotification(notification) - }).disposed(by: self.disposeBag) } + callService.currentCall(callId: callID).filter({ call in + return (call.state == .over || call.state == .failure) + }).single() + .observeOn(MainScheduler.instance) + .subscribe(onNext: { _ in + let content = UNMutableNotificationContent() + content.title = NotificationCallTitle.missedCall.getString() + content.body = name + content.sound = UNNotificationSound.default + content.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber + let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.01, repeats: false) + let notificationRequest = UNNotificationRequest(identifier: callID, content: content, trigger: notificationTrigger) + UNUserNotificationCenter.current().add(notificationRequest) { (error) in + if let error = error { + print("Unable to Add Notification Request (\(error), \(error.localizedDescription))") + } + } + }).disposed(by: self.disposeBag) } class func isEnabled() -> Bool { diff --git a/Ring/Ring/Protocols/ConversationNavigation.swift b/Ring/Ring/Protocols/ConversationNavigation.swift index fd2d72a8e..36bc4cbd1 100644 --- a/Ring/Ring/Protocols/ConversationNavigation.swift +++ b/Ring/Ring/Protocols/ConversationNavigation.swift @@ -45,6 +45,7 @@ protocol ConversationNavigation: class { extension ConversationNavigation where Self: Coordinator, Self: StateableResponsive { + // swiftlint:disable cyclomatic_complexity func callbackPlaceCall() { self.stateSubject.subscribe(onNext: { [unowned self] (state) in guard let state = state as? ConversationState else { return } diff --git a/Ring/Ring/Services/AccountsService.swift b/Ring/Ring/Services/AccountsService.swift index 73a524805..0f29ec745 100644 --- a/Ring/Ring/Services/AccountsService.swift +++ b/Ring/Ring/Services/AccountsService.swift @@ -486,10 +486,7 @@ class AccountsService: AccountAdapterDelegate { func setDetails(forAccountId accountId: String) { let details = self.getAccountDetails(fromAccountId: accountId) - var filename = "default.wav" - if #available(iOS 10.0, *) { - filename = "" - } + let filename = "" if details .get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.ringtonePath)) == filename && details diff --git a/Ring/Ring/Services/CallsProviderDelegate.swift b/Ring/Ring/Services/CallsProviderDelegate.swift index a7b924d95..83fb0442b 100644 --- a/Ring/Ring/Services/CallsProviderDelegate.swift +++ b/Ring/Ring/Services/CallsProviderDelegate.swift @@ -23,9 +23,7 @@ import CallKit import RxSwift class CallsProviderDelegate: NSObject { - @available(iOS 10.0, *) private lazy var provider: CXProvider? = nil - @available(iOS 10.0, *) private lazy var callController = CXCallController() let responseStream = PublishSubject<ServiceEvent>() var sharedResponseStream: Observable<ServiceEvent> @@ -34,25 +32,21 @@ class CallsProviderDelegate: NSObject { override init() { self.sharedResponseStream = responseStream.share() super.init() - if #available(iOS 10.0, *) { - let providerConfiguration = CXProviderConfiguration(localizedName: "Jami") + let providerConfiguration = CXProviderConfiguration(localizedName: "Jami") - providerConfiguration.supportsVideo = true - providerConfiguration.supportedHandleTypes = [.generic, .phoneNumber] - providerConfiguration.ringtoneSound = "default.wav" - providerConfiguration.iconTemplateImageData = UIImage(asset: Asset.jamiLogo)?.pngData() - providerConfiguration.maximumCallGroups = 1 - providerConfiguration.maximumCallsPerCallGroup = 1 + providerConfiguration.supportsVideo = true + providerConfiguration.supportedHandleTypes = [.generic, .phoneNumber] + providerConfiguration.ringtoneSound = "default.wav" + providerConfiguration.iconTemplateImageData = UIImage(asset: Asset.jamiLogo)?.pngData() + providerConfiguration.maximumCallGroups = 1 + providerConfiguration.maximumCallsPerCallGroup = 1 - provider = CXProvider(configuration: providerConfiguration) - provider?.setDelegate(self, queue: nil) - } + provider = CXProvider(configuration: providerConfiguration) + provider?.setDelegate(self, queue: nil) self.responseStream.disposed(by: disposeBag) } } -// MARK: - iOS 10 -@available(iOS 10.0, *) extension CallsProviderDelegate { func stopCall(callUUID: UUID) { let callController = CXCallController() @@ -134,7 +128,6 @@ extension CallsProviderDelegate { } } // MARK: - CXProviderDelegate -@available(iOS 10.0, *) extension CallsProviderDelegate: CXProviderDelegate { func providerDidReset(_ provider: CXProvider) { } diff --git a/Ring/Ring/Services/CallsService.swift b/Ring/Ring/Services/CallsService.swift index 3f0c5807b..ed56f8e90 100644 --- a/Ring/Ring/Services/CallsService.swift +++ b/Ring/Ring/Services/CallsService.swift @@ -382,7 +382,7 @@ class CallsService: CallsAdapterDelegate { } // MARK: CallsAdapterDelegate - + // swiftlint:disable cyclomatic_complexity func didChangeCallState(withCallId callId: String, state: String, stateCode: NSInteger) { if let callDictionary = self.callsAdapter.callDetails(withCallId: callId) { diff --git a/Ring/Ring/Services/ConversationsManager.swift b/Ring/Ring/Services/ConversationsManager.swift index a774bb7d1..d5b9c3e51 100644 --- a/Ring/Ring/Services/ConversationsManager.swift +++ b/Ring/Ring/Services/ConversationsManager.swift @@ -45,19 +45,63 @@ class ConversationsManager: MessagesAdapterDelegate { self.dataTransferService = dataTransferService self.callService = callService MessagesAdapter.delegate = self + subscribeFileTransferEvents() + subscribeCallsEvents() + } + func subscribeCallsEvents() { + self.callService.newMessage.filter({ (event) in + return event.eventType == ServiceEventType.newIncomingMessage + }) + .subscribe(onNext: { [unowned self] event in + guard let accountId: String = event.getEventInput(ServiceEventInput.accountId), + let messageContent: String = event.getEventInput(ServiceEventInput.content), + let peerUri: String = event.getEventInput(ServiceEventInput.peerUri) + else {return} + self.handleNewMessage(from: peerUri, + to: accountId, + messageId: "", + message: messageContent, + peerName: event.getEventInput(ServiceEventInput.name)) + }) + .disposed(by: disposeBag) + + self.callService.newMessage.filter({ (event) in + return event.eventType == ServiceEventType.newOutgoingMessage + }) + .subscribe(onNext: { [unowned self] event in + guard let accountId: String = event.getEventInput(ServiceEventInput.accountId), + let messageContent: String = event.getEventInput(ServiceEventInput.content), + let peerUri: String = event.getEventInput(ServiceEventInput.peerUri), + let accountURi: String = event.getEventInput(ServiceEventInput.accountUri) + else {return} + let message = self.conversationService.createMessage(withId: "", + withContent: messageContent, + byAuthor: accountURi, + generated: false, + incoming: false) + self.conversationService.saveMessage(message: message, + toConversationWith: peerUri, + toAccountId: accountId, + shouldRefreshConversations: true) + .subscribe() + .disposed(by: self.disposeBag) + }) + .disposed(by: disposeBag) + } + func subscribeFileTransferEvents() { self.dataTransferService .sharedResponseStream .filter({ (event) in return event.eventType == ServiceEventType.dataTransferCreated || - event.eventType == ServiceEventType.dataTransferChanged + event.eventType == ServiceEventType.dataTransferChanged }) .subscribe(onNext: { [unowned self] event in guard let transferId: UInt64 = event.getEventInput(ServiceEventInput.transferId), - let transferInfo = self.dataTransferService.getTransferInfo(withId: transferId), - let currentAccount = self.accountsService.currentAccount else { - self.log.error("ConversationsManager: can't find transferInfo") - return + let transferInfo = self.dataTransferService.getTransferInfo(withId: transferId), + let currentAccount = self.accountsService.currentAccount else { + self.log.error("ConversationsManager: can't find transferInfo") + return } switch event.eventType { case .dataTransferCreated: @@ -73,7 +117,6 @@ class ConversationsManager: MessagesAdapterDelegate { .getTransferInfo(withId: transferId) else {return} self.autoAcceptTransfer(transferInfo: transferInfo, transferId: transferId, accountId: transferInfo.accountId) }).disposed(by: self.disposeBag) - case .dataTransferChanged: self.log.debug("ConversationsManager: dataTransferChanged - id:\(transferId) status:\(stringFromEventCode(with: transferInfo.lastEvent))") var status: DataTransferStatus = .unknown @@ -104,45 +147,6 @@ class ConversationsManager: MessagesAdapterDelegate { } }) .disposed(by: disposeBag) - self.callService.newMessage.filter({ (event) in - return event.eventType == ServiceEventType.newIncomingMessage - }) - .subscribe(onNext: { [unowned self] event in - guard let accountId: String = event.getEventInput(ServiceEventInput.accountId), - let messageContent: String = event.getEventInput(ServiceEventInput.content), - let peerUri: String = event.getEventInput(ServiceEventInput.peerUri) - else {return} - self.handleNewMessage(from: peerUri, - to: accountId, - messageId: "", - message: messageContent, - peerName: event.getEventInput(ServiceEventInput.name)) - }) - .disposed(by: disposeBag) - - self.callService.newMessage.filter({ (event) in - return event.eventType == ServiceEventType.newOutgoingMessage - }) - .subscribe(onNext: { [unowned self] event in - guard let accountId: String = event.getEventInput(ServiceEventInput.accountId), - let messageContent: String = event.getEventInput(ServiceEventInput.content), - let peerUri: String = event.getEventInput(ServiceEventInput.peerUri), - let accountURi: String = event.getEventInput(ServiceEventInput.accountUri) - - else {return} - let message = self.conversationService.createMessage(withId: "", - withContent: messageContent, - byAuthor: accountURi, - generated: false, - incoming: false) - self.conversationService.saveMessage(message: message, - toConversationWith: peerUri, - toAccountId: accountId, - shouldRefreshConversations: true) - .subscribe() - .disposed(by: self.disposeBag) - }) - .disposed(by: disposeBag) } func prepareConversationsForAccount(accountId: String) { diff --git a/Ring/Ring/Services/ConversationsService.swift b/Ring/Ring/Services/ConversationsService.swift index 10d47aed0..b7ae436a7 100644 --- a/Ring/Ring/Services/ConversationsService.swift +++ b/Ring/Ring/Services/ConversationsService.swift @@ -22,6 +22,7 @@ import RxSwift import SwiftyBeaver +// swiftlint:disable type_body_length class ConversationsService { /** diff --git a/Ring/Ring/Services/VideoService.swift b/Ring/Ring/Services/VideoService.swift index 7668ab485..d776e8559 100644 --- a/Ring/Ring/Services/VideoService.swift +++ b/Ring/Ring/Services/VideoService.swift @@ -193,11 +193,8 @@ class FrameExtractor: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate { } func selectCaptureDevice(withPosition position: AVCaptureDevice.Position) -> AVCaptureDevice? { - let devices = AVCaptureDevice.devices(for: AVMediaType.video) - for device in devices where device.position == position { - return device - } - return nil + let devices = AVCaptureDevice.DiscoverySession.init(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: AVMediaType.video, position: position).devices + return devices.first } func switchCamera() -> Completable { -- GitLab