Merge branch 'mkirk/swift5'

pull/2/head
Michael Kirk 6 years ago
commit d05fdb19bd

@ -1 +1 @@
Subproject commit 1da2265dd490b9d232a963b26a0ae3da26e6b71c
Subproject commit 0473f1e7065fdbf5d80d6fd5b86c770f902960b0

@ -488,6 +488,7 @@
4C4BC6C32102D697004040C9 /* ContactDiscoveryOperationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4BC6C22102D697004040C9 /* ContactDiscoveryOperationTest.swift */; };
4C5250D221E7BD7D00CE3D95 /* PhoneNumberValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5250D121E7BD7D00CE3D95 /* PhoneNumberValidator.swift */; };
4C5250D421E7C51900CE3D95 /* PhoneNumberValidatorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5250D321E7C51900CE3D95 /* PhoneNumberValidatorTest.swift */; };
4C586926224FAB83003FD070 /* AVAudioSession+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C586925224FAB83003FD070 /* AVAudioSession+OWS.m */; };
4C618199219DF03A009BD6B5 /* OWSButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C618198219DF03A009BD6B5 /* OWSButton.swift */; };
4C61819F219E1796009BD6B5 /* typing-animation-dark.gif in Resources */ = {isa = PBXBuildFile; fileRef = 4C61819E219E1795009BD6B5 /* typing-animation-dark.gif */; };
4C63CC00210A620B003AE45C /* SignalTSan.supp in Resources */ = {isa = PBXBuildFile; fileRef = 4C63CBFF210A620B003AE45C /* SignalTSan.supp */; };
@ -1239,6 +1240,8 @@
4C4BC6C22102D697004040C9 /* ContactDiscoveryOperationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ContactDiscoveryOperationTest.swift; path = contact/ContactDiscoveryOperationTest.swift; sourceTree = "<group>"; };
4C5250D121E7BD7D00CE3D95 /* PhoneNumberValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneNumberValidator.swift; sourceTree = "<group>"; };
4C5250D321E7C51900CE3D95 /* PhoneNumberValidatorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneNumberValidatorTest.swift; sourceTree = "<group>"; };
4C586924224FAB83003FD070 /* AVAudioSession+OWS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "AVAudioSession+OWS.h"; path = "util/UI Categories/AVAudioSession+OWS.h"; sourceTree = "<group>"; };
4C586925224FAB83003FD070 /* AVAudioSession+OWS.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "AVAudioSession+OWS.m"; path = "util/UI Categories/AVAudioSession+OWS.m"; sourceTree = "<group>"; };
4C618198219DF03A009BD6B5 /* OWSButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSButton.swift; sourceTree = "<group>"; };
4C61819E219E1795009BD6B5 /* typing-animation-dark.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "typing-animation-dark.gif"; sourceTree = "<group>"; };
4C63CBFF210A620B003AE45C /* SignalTSan.supp */ = {isa = PBXFileReference; lastKnownFileType = text; path = SignalTSan.supp; sourceTree = "<group>"; };
@ -2692,6 +2695,8 @@
EF764C331DB67CC5000D9A87 /* UIViewController+Permissions.h */,
EF764C341DB67CC5000D9A87 /* UIViewController+Permissions.m */,
45B5360D206DD8BB00D61655 /* UIResponder+OWS.swift */,
4C586924224FAB83003FD070 /* AVAudioSession+OWS.h */,
4C586925224FAB83003FD070 /* AVAudioSession+OWS.m */,
);
name = "UI Categories";
path = ..;
@ -2869,13 +2874,13 @@
attributes = {
LastSwiftUpdateCheck = 0920;
LastTestingUpgradeCheck = 0600;
LastUpgradeCheck = 0940;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "Open Whisper Systems";
TargetAttributes = {
453518671FC635DD00210559 = {
CreatedOnToolsVersion = 9.2;
DevelopmentTeam = U68MSDN6DR;
LastSwiftMigration = 0910;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.ApplicationGroups.iOS = {
@ -2895,12 +2900,12 @@
453518911FC63DBF00210559 = {
CreatedOnToolsVersion = 9.2;
DevelopmentTeam = U68MSDN6DR;
LastSwiftMigration = 0930;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
D221A088169C9E5E00537ABF = {
DevelopmentTeam = U68MSDN6DR;
LastSwiftMigration = 0930;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.ApplicationGroups.iOS = {
@ -2931,7 +2936,7 @@
};
D221A0A9169C9E5F00537ABF = {
DevelopmentTeam = U68MSDN6DR;
LastSwiftMigration = 0930;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
TestTargetID = D221A088169C9E5E00537ABF;
};
@ -2939,7 +2944,7 @@
};
buildConfigurationList = D221A083169C9E5E00537ABF /* Build configuration list for PBXProject "Signal" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
@ -3660,6 +3665,7 @@
4517642B1DE939FD00EDB8B9 /* ContactCell.swift in Sources */,
34EA69402194933900702471 /* MediaDownloadView.swift in Sources */,
340FC8AB204DAC8D007AEB0F /* DomainFrontingCountryViewController.m in Sources */,
4C586926224FAB83003FD070 /* AVAudioSession+OWS.m in Sources */,
3496744D2076768700080B5F /* OWSMessageBubbleView.m in Sources */,
34B3F8751E8DF1700035BE1A /* CallViewController.swift in Sources */,
4C4AE6A1224AF35700D4AF6F /* SendMediaNavigationController.swift in Sources */,
@ -3914,7 +3920,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OBJC_BRIDGING_HEADER = "SignalShareExtension/SignalShareExtension-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Debug;
@ -3979,7 +3985,7 @@
SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "SignalShareExtension/SignalShareExtension-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
VALIDATE_PRODUCT = YES;
};
@ -4032,8 +4038,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -4106,8 +4111,7 @@
SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
@ -4328,8 +4332,7 @@
SDKROOT = iphoneos;
SWIFT_OBJC_BRIDGING_HEADER = "Signal/src/Signal-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TEST_AFTER_BUILD = YES;
VALID_ARCHS = "arm64 armv7 armv7s";
WRAPPER_EXTENSION = app;
@ -4392,8 +4395,7 @@
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = iphoneos;
SWIFT_OBJC_BRIDGING_HEADER = "Signal/src/Signal-Bridging-Header.h";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TEST_AFTER_BUILD = YES;
VALID_ARCHS = "arm64 armv7 armv7s";
WRAPPER_EXTENSION = app;
@ -4452,8 +4454,7 @@
PROVISIONING_PROFILE = "";
SWIFT_OBJC_BRIDGING_HEADER = "Signal/test/SignalTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUNDLE_LOADER)";
VALID_ARCHS = "arm64 armv7s armv7 i386 x86_64";
};
@ -4510,8 +4511,7 @@
PROVISIONING_PROFILE = "";
SWIFT_OBJC_BRIDGING_HEADER = "Signal/test/SignalTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUNDLE_LOADER)";
VALID_ARCHS = "arm64 armv7s armv7 i386 x86_64";
};

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0940"
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0940"
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -28,7 +28,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4D5E7522A33906C902399C86F0A95AA5"
BlueprintIdentifier = "EF7BE58B1F949AF31E4AF4FD37150A86"
BuildableName = "SignalServiceKit.framework"
BlueprintName = "SignalServiceKit"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@ -56,7 +56,7 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "AB62203226FE5032747AA668B1E97176"
BlueprintIdentifier = "2349E04BB99C0118E8F578CCBEAAC665"
BuildableName = "SignalServiceKit-Unit-Tests.xctest"
BlueprintName = "SignalServiceKit-Unit-Tests"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@ -66,7 +66,7 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "BC89BC6B06642C78EABF18B43FFB41DE"
BlueprintIdentifier = "3AC929F2E4978F42ED9E9EA232D7247B"
BuildableName = "SignalCoreKit-Unit-Tests.xctest"
BlueprintName = "SignalCoreKit-Unit-Tests"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@ -76,7 +76,7 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E012D804E31EC876E21973F300B46CCB"
BlueprintIdentifier = "5B34FB0B5ABA685EF33F1BA1C388F016"
BuildableName = "AxolotlKit-Unit-Tests.xctest"
BlueprintName = "AxolotlKit-Unit-Tests"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@ -86,7 +86,7 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B4A8ABAC14D962F8F42814238460DF44"
BlueprintIdentifier = "D85B45003BA81D72F606FDF3EB4B4E1C"
BuildableName = "Curve25519Kit-Unit-Tests.xctest"
BlueprintName = "Curve25519Kit-Unit-Tests"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@ -96,7 +96,7 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E5C44C64CDE3569B16010274DCD48BCC"
BlueprintIdentifier = "F9C2DA0BADF4F69559F0AA5BB4FC1E06"
BuildableName = "HKDFKit-Unit-Tests.xctest"
BlueprintName = "HKDFKit-Unit-Tests"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@ -106,7 +106,7 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00649589DE58D9DECF419A3CC47D6924"
BlueprintIdentifier = "92057C418B970541FF6BE6E64A49D8C2"
BuildableName = "SignalMetadataKit-Unit-Tests.xctest"
BlueprintName = "SignalMetadataKit-Unit-Tests"
ReferencedContainer = "container:Pods/Pods.xcodeproj">

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0940"
LastUpgradeVersion = "1020"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction

@ -5,7 +5,7 @@
<key>BuildDetails</key>
<dict>
<key>CarthageVersion</key>
<string>0.31.2</string>
<string>0.32.0</string>
<key>OSXVersion</key>
<string>10.14.3</string>
<key>WebRTCCommit</key>

@ -86,7 +86,7 @@ public class AccountManager: NSObject {
return Promise { resolver in
tsAccountManager.verifyAccount(withCode: verificationCode,
pin: pin,
success: resolver.fulfill,
success: { resolver.fulfill(()) },
failure: resolver.reject)
}
}
@ -109,7 +109,7 @@ public class AccountManager: NSObject {
return Promise { resolver in
tsAccountManager.registerForPushNotifications(pushToken: pushToken,
voipToken: voipToken,
success: resolver.fulfill,
success: { resolver.fulfill(()) },
failure: resolver.reject)
}
}

@ -27,12 +27,12 @@ class CompareSafetyNumbersActivity: UIActivity {
// MARK: UIActivity
override class var activityCategory: UIActivityCategory {
override class var activityCategory: UIActivity.Category {
get { return .action }
}
override var activityType: UIActivityType? {
get { return UIActivityType(rawValue: CompareSafetyNumbersActivityType) }
override var activityType: UIActivity.ActivityType? {
get { return UIActivity.ActivityType(rawValue: CompareSafetyNumbersActivityType) }
}
override var activityTitle: String? {

@ -6,6 +6,7 @@
#import <UIKit/UIKit.h>
// Separate iOS Frameworks from other imports.
#import "AVAudioSession+OWS.h"
#import "AppSettingsViewController.h"
#import "AttachmentUploadView.h"
#import "AvatarViewHelper.h"

@ -1,16 +1,16 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@objc public extension UIApplication {
@objc public var frontmostViewControllerIgnoringAlerts: UIViewController? {
public var frontmostViewControllerIgnoringAlerts: UIViewController? {
return findFrontmostViewController(ignoringAlerts: true)
}
@objc public var frontmostViewController: UIViewController? {
public var frontmostViewController: UIViewController? {
return findFrontmostViewController(ignoringAlerts: false)
}
@ -26,8 +26,8 @@ import Foundation
return viewController.findFrontmostViewController(ignoringAlerts)
}
@objc public func openSystemSettings() {
openURL(URL(string: UIApplicationOpenSettingsURLString)!)
public func openSystemSettings() {
openURL(URL(string: UIApplication.openSettingsURLString)!)
}
}

@ -51,8 +51,9 @@ enum NotificationHapticFeedbackType {
case error, success, warning
}
@available(iOS 10.0, *)
extension NotificationHapticFeedbackType {
var uiNotificationFeedbackType: UINotificationFeedbackType {
var uiNotificationFeedbackType: UINotificationFeedbackGenerator.FeedbackType {
switch self {
case .error: return .error
case .success: return .success

@ -281,8 +281,8 @@ extension OWSSound {
func notificationSound(isQuiet: Bool) -> UNNotificationSound {
guard let filename = OWSSounds.filename(for: self, quiet: isQuiet) else {
owsFailDebug("filename was unexpectedly nil")
return UNNotificationSound.default()
return UNNotificationSound.default
}
return UNNotificationSound(named: filename)
return UNNotificationSound(named: UNNotificationSoundName(rawValue: filename))
}
}

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -128,7 +128,7 @@ class AddContactShareToExistingContactViewController: ContactsPicker, ContactsPi
// We want to pop *this* view *and* the still presented CNContactViewController in a single animation.
// Note this happens for *cancel* and for *done*. Unfortunately, I don't know of a way to detect the difference
// between the two, since both just call this method.
guard let myIndex = navigationController.viewControllers.index(of: self) else {
guard let myIndex = navigationController.viewControllers.firstIndex(of: self) else {
owsFailDebug("myIndex was unexpectedly nil")
navigationController.popViewController(animated: true)
navigationController.popViewController(animated: true)

@ -124,7 +124,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
}
// Don't use receiver when video is enabled. Only bluetooth or speaker
return portDescription.portType != AVAudioSessionPortBuiltInMic
return portDescription.portType != AVAudioSession.Port.builtInMic
}
}
return Set(appropriateForVideo)
@ -602,7 +602,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
internal func updateLocalVideoLayout() {
if !localVideoView.isHidden {
localVideoView.superview?.bringSubview(toFront: localVideoView)
localVideoView.superview?.bringSubviewToFront(localVideoView)
}
updateCallUI(callState: call.state)

@ -285,7 +285,7 @@ class ColorPickerView: UIView, ColorViewDelegate {
let kRowLength = 4
let rows: [UIView] = colorViews.chunked(by: kRowLength).map { colorViewsInRow in
let row = UIStackView(arrangedSubviews: colorViewsInRow)
row.distribution = UIStackViewDistribution.equalSpacing
row.distribution = UIStackView.Distribution.equalSpacing
return row
}
let rowsStackView = UIStackView(arrangedSubviews: rows)

@ -320,7 +320,7 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate {
// Show no action buttons for contacts without a phone number.
break
case .unknown:
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
topView.addSubview(activityIndicator)
activityIndicator.autoPinEdge(.top, to: .bottom, of: lastView, withOffset: 10)
activityIndicator.autoHCenterInSuperview()

@ -124,7 +124,7 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
// Auto size cells for dynamic type
tableView.estimatedRowHeight = 60.0
tableView.rowHeight = UITableViewAutomaticDimension
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 60
tableView.allowsMultipleSelection = allowsMultipleSelection
@ -136,7 +136,7 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
reloadContacts()
updateSearchResults(searchText: "")
NotificationCenter.default.addObserver(self, selector: #selector(self.didChangePreferredContentSize), name: NSNotification.Name.UIContentSizeCategoryDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.didChangePreferredContentSize), name: UIContentSizeCategory.didChangeNotification, object: nil)
}
@objc
@ -172,7 +172,7 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
let title = NSLocalizedString("INVITE_FLOW_REQUIRES_CONTACT_ACCESS_TITLE", comment: "Alert title when contacts disabled while trying to invite contacts to signal")
let body = NSLocalizedString("INVITE_FLOW_REQUIRES_CONTACT_ACCESS_BODY", comment: "Alert body when contacts disabled while trying to invite contacts to signal")
let alert = UIAlertController(title: title, message: body, preferredStyle: UIAlertControllerStyle.alert)
let alert = UIAlertController(title: title, message: body, preferredStyle: .alert)
let dismissText = CommonStrings.cancelButton

@ -204,8 +204,8 @@ public class ConversationMediaView: UIView {
animatedImageView.contentMode = .scaleAspectFill
// Use trilinear filters for better scaling quality at
// some performance cost.
animatedImageView.layer.minificationFilter = kCAFilterTrilinear
animatedImageView.layer.magnificationFilter = kCAFilterTrilinear
animatedImageView.layer.minificationFilter = .trilinear
animatedImageView.layer.magnificationFilter = .trilinear
animatedImageView.backgroundColor = Theme.offBackgroundColor
addSubview(animatedImageView)
animatedImageView.autoPinEdgesToSuperviewEdges()
@ -263,8 +263,8 @@ public class ConversationMediaView: UIView {
stillImageView.contentMode = .scaleAspectFill
// Use trilinear filters for better scaling quality at
// some performance cost.
stillImageView.layer.minificationFilter = kCAFilterTrilinear
stillImageView.layer.magnificationFilter = kCAFilterTrilinear
stillImageView.layer.minificationFilter = .trilinear
stillImageView.layer.magnificationFilter = .trilinear
stillImageView.backgroundColor = Theme.offBackgroundColor
addSubview(stillImageView)
stillImageView.autoPinEdgesToSuperviewEdges()
@ -318,8 +318,8 @@ public class ConversationMediaView: UIView {
stillImageView.contentMode = .scaleAspectFill
// Use trilinear filters for better scaling quality at
// some performance cost.
stillImageView.layer.minificationFilter = kCAFilterTrilinear
stillImageView.layer.magnificationFilter = kCAFilterTrilinear
stillImageView.layer.minificationFilter = .trilinear
stillImageView.layer.magnificationFilter = .trilinear
stillImageView.backgroundColor = Theme.offBackgroundColor
addSubview(stillImageView)
@ -380,7 +380,7 @@ public class ConversationMediaView: UIView {
private func configure(forError error: MediaError) {
backgroundColor = (Theme.isDarkThemeEnabled ? .ows_gray90 : .ows_gray05)
let icon: UIImage
switch (error) {
switch error {
case .failed:
guard let asset = UIImage(named: "media_retry") else {
owsFailDebug("Missing image")

@ -157,7 +157,7 @@ public class MediaAlbumCellView: UIStackView {
// the "more" item, if any.
continue
}
guard let index = itemViews.index(of: itemView) else {
guard let index = itemViews.firstIndex(of: itemView) else {
owsFailDebug("Couldn't determine index of item view.")
continue
}
@ -188,14 +188,14 @@ public class MediaAlbumCellView: UIStackView {
}
private func newRow(rowViews: [ConversationMediaView],
axis: UILayoutConstraintAxis,
axis: NSLayoutConstraint.Axis,
viewSize: CGFloat) -> UIStackView {
autoSet(viewSize: viewSize, ofViews: rowViews)
return newRow(rowViews: rowViews, axis: axis)
}
private func newRow(rowViews: [ConversationMediaView],
axis: UILayoutConstraintAxis) -> UIStackView {
axis: NSLayoutConstraint.Axis) -> UIStackView {
let stackView = UIStackView(arrangedSubviews: rowViews)
stackView.axis = axis
stackView.spacing = MediaAlbumCellView.kSpacingPts

@ -105,7 +105,7 @@ public class MediaDownloadView: UIView {
shapeLayer1.path = bezierPath1.cgPath
let fillColor1: UIColor = UIColor(white: 1.0, alpha: 0.4)
shapeLayer1.fillColor = fillColor1.cgColor
shapeLayer1.fillRule = kCAFillRuleEvenOdd
shapeLayer1.fillRule = .evenOdd
let bezierPath2 = UIBezierPath()
bezierPath2.addArc(withCenter: center, radius: outerRadius, startAngle: startAngle, endAngle: endAngle, clockwise: true)

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -110,7 +110,7 @@ public class MediaUploadView: UIView {
bezierPath2.append(UIBezierPath(ovalIn: outerCircleBounds))
shapeLayer2.path = bezierPath2.cgPath
shapeLayer2.fillColor = UIColor(white: 1.0, alpha: 0.4).cgColor
shapeLayer2.fillRule = kCAFillRuleEvenOdd
shapeLayer2.fillRule = .evenOdd
CATransaction.commit()
}

@ -113,7 +113,7 @@ public class ConversationHeaderView: UIStackView {
public override var intrinsicContentSize: CGSize {
// Grow to fill as much of the navbar as possible.
return UILayoutFittingExpandedSize
return UIView.layoutFittingExpandedSize
}
@objc

@ -184,7 +184,7 @@ import SignalMessaging
path.usesEvenOddFillRule = true
layer.path = path.cgPath
layer.fillRule = kCAFillRuleEvenOdd
layer.fillRule = .evenOdd
layer.fillColor = UIColor.black.cgColor
layer.opacity = 0.7
}
@ -341,7 +341,7 @@ import SignalMessaging
var lastPinchScale: CGFloat = 1.0
@objc func handlePinch(sender: UIPinchGestureRecognizer) {
switch (sender.state) {
switch sender.state {
case .possible:
break
case .began:
@ -398,7 +398,7 @@ import SignalMessaging
var srcTranslationAtPanStart: CGPoint = CGPoint.zero
@objc func handlePan(sender: UIPanGestureRecognizer) {
switch (sender.state) {
switch sender.state {
case .possible:
break
case .began:

@ -221,7 +221,7 @@ class GifPickerCell: UICollectionViewCell {
self.backgroundColor = nil
if self.isCellSelected {
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
let activityIndicator = UIActivityIndicatorView(style: .gray)
self.activityIndicator = activityIndicator
addSubview(activityIndicator)
activityIndicator.autoCenterInSuperview()

@ -216,7 +216,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
searchErrorView.isUserInteractionEnabled = true
searchErrorView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(retryTapped)))
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
let activityIndicator = UIActivityIndicatorView(style: .gray)
self.activityIndicator = activityIndicator
self.view.addSubview(activityIndicator)
activityIndicator.autoHCenterInSuperview()
@ -349,7 +349,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
path.append(UIBezierPath(rect: cellRect))
layer.path = path.cgPath
layer.fillRule = kCAFillRuleEvenOdd
layer.fillRule = .evenOdd
layer.fillColor = UIColor.black.cgColor
layer.opacity = 0.7
}

@ -64,7 +64,7 @@ class ConversationSearchViewController: UITableViewController, BlockListCacheDel
blockListCache = BlockListCache()
blockListCache.startObservingAndSyncState(delegate: self)
tableView.rowHeight = UITableViewAutomaticDimension
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 60
tableView.separatorColor = Theme.cellSeparatorColor
@ -272,7 +272,7 @@ class ConversationSearchViewController: UITableViewController, BlockListCacheDel
if let messageSnippet = searchResult.snippet {
overrideSnippet = NSAttributedString(string: messageSnippet,
attributes: [
NSAttributedStringKey.foregroundColor: Theme.secondaryColor
NSAttributedString.Key.foregroundColor: Theme.secondaryColor
])
} else {
owsFailDebug("message search result is missing message snippet")
@ -296,7 +296,7 @@ class ConversationSearchViewController: UITableViewController, BlockListCacheDel
guard nil != self.tableView(tableView, titleForHeaderInSection: section) else {
return 0
}
return UITableViewAutomaticDimension
return UITableView.automaticDimension
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
@ -433,7 +433,7 @@ class EmptySearchResultCell: UITableViewCell {
static let reuseIdentifier = "EmptySearchResultCell"
let messageLabel: UILabel
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
self.messageLabel = UILabel()
super.init(style: style, reuseIdentifier: reuseIdentifier)

@ -137,14 +137,10 @@ public class LongTextViewController: OWSViewController {
messageTextView.text = ""
}
// RADAR #18669
// https://github.com/lionheart/openradar-mirror/issues/18669
//
// UITextViews linkTextAttributes property has type [String : Any]! but should be [NSAttributedStringKey : Any]! in Swift 4.
let linkTextAttributes: [String: Any] = [
NSAttributedStringKey.foregroundColor.rawValue: Theme.primaryColor,
NSAttributedStringKey.underlineColor.rawValue: Theme.primaryColor,
NSAttributedStringKey.underlineStyle.rawValue: NSUnderlineStyle.styleSingle.rawValue
let linkTextAttributes: [NSAttributedString.Key: Any] = [
NSAttributedString.Key.foregroundColor: Theme.primaryColor,
NSAttributedString.Key.underlineColor: Theme.primaryColor,
NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue
]
messageTextView.linkTextAttributes = linkTextAttributes

@ -282,8 +282,8 @@ class MediaGalleryNavigationController: OWSNavigationController {
presentationView.isHidden = true
presentationView.clipsToBounds = true
presentationView.layer.allowsEdgeAntialiasing = true
presentationView.layer.minificationFilter = kCAFilterTrilinear
presentationView.layer.magnificationFilter = kCAFilterTrilinear
presentationView.layer.minificationFilter = .trilinear
presentationView.layer.magnificationFilter = .trilinear
presentationView.contentMode = .scaleAspectFit
guard let navigationBar = self.navigationBar as? OWSNavigationBar else {
@ -980,13 +980,13 @@ class MediaGallery: NSObject, MediaGalleryDataSource, MediaTileViewControllerDel
if let completionBlock = completion {
Bench(title: "calculating changes for collectionView") {
// FIXME can we avoid this index offset?
let dateIndices = newDates.map { sectionDates.index(of: $0)! + 1 }
let dateIndices = newDates.map { sectionDates.firstIndex(of: $0)! + 1 }
let addedSections: IndexSet = IndexSet(dateIndices)
let addedItems: [IndexPath] = newGalleryItems.map { galleryItem in
let sectionIdx = sectionDates.index(of: galleryItem.galleryDate)!
let sectionIdx = sectionDates.firstIndex(of: galleryItem.galleryDate)!
let section = sections[galleryItem.galleryDate]!
let itemIdx = section.index(of: galleryItem)!
let itemIdx = section.firstIndex(of: galleryItem)!
// FIXME can we avoid this index offset?
return IndexPath(item: itemIdx, section: sectionIdx + 1)
@ -1032,14 +1032,14 @@ class MediaGallery: NSObject, MediaGalleryDataSource, MediaTileViewControllerDel
let originalSectionDates = self.sectionDates
for item in items {
guard let itemIndex = galleryItems.index(of: item) else {
guard let itemIndex = galleryItems.firstIndex(of: item) else {
owsFailDebug("removing unknown item.")
return
}
self.galleryItems.remove(at: itemIndex)
guard let sectionIndex = sectionDates.index(where: { $0 == item.galleryDate }) else {
guard let sectionIndex = sectionDates.firstIndex(where: { $0 == item.galleryDate }) else {
owsFailDebug("item with unknown date.")
return
}
@ -1049,13 +1049,13 @@ class MediaGallery: NSObject, MediaGalleryDataSource, MediaTileViewControllerDel
return
}
guard let sectionRowIndex = sectionItems.index(of: item) else {
guard let sectionRowIndex = sectionItems.firstIndex(of: item) else {
owsFailDebug("item with unknown sectionRowIndex")
return
}
// We need to calculate the index of the deleted item with respect to it's original position.
guard let originalSectionIndex = originalSectionDates.index(where: { $0 == item.galleryDate }) else {
guard let originalSectionIndex = originalSectionDates.firstIndex(where: { $0 == item.galleryDate }) else {
owsFailDebug("item with unknown date.")
return
}
@ -1065,7 +1065,7 @@ class MediaGallery: NSObject, MediaGalleryDataSource, MediaTileViewControllerDel
return
}
guard let originalSectionRowIndex = originalSectionItems.index(of: item) else {
guard let originalSectionRowIndex = originalSectionItems.firstIndex(of: item) else {
owsFailDebug("item with unknown sectionRowIndex")
return
}
@ -1095,7 +1095,7 @@ class MediaGallery: NSObject, MediaGalleryDataSource, MediaTileViewControllerDel
self.ensureGalleryItemsLoaded(.after, item: currentItem, amount: kGallerySwipeLoadBatchSize)
guard let currentIndex = galleryItems.index(of: currentItem) else {
guard let currentIndex = galleryItems.firstIndex(of: currentItem) else {
owsFailDebug("currentIndex was unexpectedly nil")
return nil
}
@ -1119,7 +1119,7 @@ class MediaGallery: NSObject, MediaGalleryDataSource, MediaTileViewControllerDel
self.ensureGalleryItemsLoaded(.before, item: currentItem, amount: kGallerySwipeLoadBatchSize)
guard let currentIndex = galleryItems.index(of: currentItem) else {
guard let currentIndex = galleryItems.firstIndex(of: currentItem) else {
owsFailDebug("currentIndex was unexpectedly nil")
return nil
}

@ -48,7 +48,7 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
return currentViewController.galleryItemBox.value
}
public func setCurrentItem(_ item: MediaGalleryItem, direction: UIPageViewControllerNavigationDirection, animated isAnimated: Bool) {
public func setCurrentItem(_ item: MediaGalleryItem, direction: UIPageViewController.NavigationDirection, animated isAnimated: Bool) {
guard let galleryPage = self.buildGalleryPage(galleryItem: item) else {
owsFailDebug("unexpectedly unable to build new gallery page")
return
@ -75,9 +75,10 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
let kSpacingBetweenItems: CGFloat = 20
let options: [UIPageViewController.OptionsKey: Any] = [.interPageSpacing: kSpacingBetweenItems]
super.init(transitionStyle: .scroll,
navigationOrientation: .horizontal,
options: [UIPageViewControllerOptionInterPageSpacingKey: kSpacingBetweenItems])
options: options)
self.dataSource = self
self.delegate = self
@ -800,7 +801,7 @@ extension MediaPageViewController: GalleryRailViewDelegate {
return
}
let direction: UIPageViewControllerNavigationDirection
let direction: UIPageViewController.NavigationDirection
direction = currentItem.albumIndex < targetItem.albumIndex ? .forward : .reverse
self.setCurrentItem(targetItem, direction: direction, animated: true)

@ -95,8 +95,8 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryDa
collectionView.backgroundColor = Theme.darkThemeBackgroundColor
collectionView.register(PhotoGridViewCell.self, forCellWithReuseIdentifier: PhotoGridViewCell.reuseIdentifier)
collectionView.register(MediaGallerySectionHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: MediaGallerySectionHeader.reuseIdentifier)
collectionView.register(MediaGalleryStaticHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: MediaGalleryStaticHeader.reuseIdentifier)
collectionView.register(MediaGallerySectionHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: MediaGallerySectionHeader.reuseIdentifier)
collectionView.register(MediaGalleryStaticHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: MediaGalleryStaticHeader.reuseIdentifier)
collectionView.delegate = self
@ -113,10 +113,10 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryDa
}
private func indexPath(galleryItem: MediaGalleryItem) -> IndexPath? {
guard let sectionIdx = galleryDates.index(of: galleryItem.galleryDate) else {
guard let sectionIdx = galleryDates.firstIndex(of: galleryItem.galleryDate) else {
return nil
}
guard let rowIdx = galleryItems[galleryItem.galleryDate]!.index(of: galleryItem) else {
guard let rowIdx = galleryItems[galleryItem.galleryDate]!.firstIndex(of: galleryItem) else {
return nil
}
@ -311,7 +311,7 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryDa
return sectionHeader
}
if (kind == UICollectionElementKindSectionHeader) {
if (kind == UICollectionView.elementKindSectionHeader) {
switch indexPath.section {
case kLoadOlderSectionIdx:
guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: MediaGalleryStaticHeader.reuseIdentifier, for: indexPath) as? MediaGalleryStaticHeader else {

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
@ -44,7 +44,7 @@ public class OWS2FAReminderViewController: UIViewController, PinEntryViewDelegat
let instructionsTextHeader = NSLocalizedString("REMINDER_2FA_BODY_HEADER", comment: "Body header for when user is periodically prompted to enter their registration lock PIN")
let instructionsTextBody = NSLocalizedString("REMINDER_2FA_BODY", comment: "Body text for when user is periodically prompted to enter their registration lock PIN")
let attributes = [NSAttributedStringKey.font: pinEntryView.boldLabelFont]
let attributes = [NSAttributedString.Key.font: pinEntryView.boldLabelFont]
let attributedInstructionsText = NSAttributedString(string: instructionsTextHeader, attributes: attributes).rtlSafeAppend(" ").rtlSafeAppend(instructionsTextBody)

@ -72,7 +72,7 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
// do nothing
} else {
// must assign titleView frame manually on older iOS
titleView.frame = CGRect(origin: .zero, size: titleView.systemLayoutSizeFitting(UILayoutFittingCompressedSize))
titleView.frame = CGRect(origin: .zero, size: titleView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize))
}
navigationItem.titleView = titleView
@ -393,7 +393,7 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
assert(self.collectionPickerController == nil)
self.collectionPickerController = collectionPickerController
addChildViewController(collectionPickerController)
addChild(collectionPickerController)
view.addSubview(collectionPickerView)
collectionPickerView.autoPinEdgesToSuperviewEdges(with: .zero, excludingEdge: .top)
@ -422,7 +422,7 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
self.titleView.rotateIcon(.down)
}.done { _ in
collectionPickerController.view.removeFromSuperview()
collectionPickerController.removeFromParentViewController()
collectionPickerController.removeFromParent()
}.retainUntilComplete()
}

@ -649,7 +649,7 @@ extension UIDeviceOrientation: CustomStringConvertible {
}
}
extension UIImageOrientation: CustomStringConvertible {
extension UIImage.Orientation: CustomStringConvertible {
public var description: String {
switch self {
case .up:

@ -245,7 +245,7 @@ class PhotoCaptureViewController: OWSViewController {
NotificationCenter.default.addObserver(self,
selector: #selector(didChangeDeviceOrientation),
name: .UIDeviceOrientationDidChange,
name: UIDevice.orientationDidChangeNotification,
object: UIDevice.current)
}

@ -53,7 +53,7 @@ class PhotoCollectionPickerController: OWSTableViewController, PhotoLibraryDeleg
let sectionItems = photoCollections.map { collection in
return OWSTableItem(customCellBlock: { self.buildTableCell(collection: collection) },
customRowHeight: UITableViewAutomaticDimension,
customRowHeight: UITableView.automaticDimension,
actionBlock: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.didSelectCollection(collection: collection)

@ -111,7 +111,7 @@ class SendMediaNavigationController: OWSNavigationController {
func fadeTo(viewControllers: [UIViewController]) {
let transition: CATransition = CATransition()
transition.duration = 0.1
transition.type = kCATransitionFade
transition.type = CATransitionType.fade
view.layer.add(transition, forKey: nil)
setViewControllers(viewControllers, animated: false)
}

@ -17,8 +17,8 @@ public class OnboardingSplashViewController: OnboardingBaseViewController {
let heroImage = UIImage(named: "onboarding_splash_hero")
let heroImageView = UIImageView(image: heroImage)
heroImageView.contentMode = .scaleAspectFit
heroImageView.layer.minificationFilter = kCAFilterTrilinear
heroImageView.layer.magnificationFilter = kCAFilterTrilinear
heroImageView.layer.minificationFilter = .trilinear
heroImageView.layer.magnificationFilter = .trilinear
heroImageView.setCompressionResistanceLow()
heroImageView.setContentHuggingVerticalLow()
heroImageView.accessibilityIdentifier = "onboarding.splash." + "heroImageView"

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -29,7 +29,7 @@ struct AudioSource: Hashable {
init(portDescription: AVAudioSessionPortDescription) {
let isBuiltInEarPiece = portDescription.portType == AVAudioSessionPortBuiltInMic
let isBuiltInEarPiece = portDescription.portType == AVAudioSession.Port.builtInMic
// portDescription.portName works well for BT linked devices, but if we are using
// the built in mic, we have "iPhone Microphone" which is a little awkward.
@ -129,7 +129,7 @@ protocol CallAudioServiceDelegate: class {
// Configure audio session so we don't prompt user with Record permission until call is connected.
audioSession.configureRTCAudio()
NotificationCenter.default.addObserver(forName: .AVAudioSessionRouteChange, object: avAudioSession, queue: nil) { _ in
NotificationCenter.default.addObserver(forName: AVAudioSession.routeChangeNotification, object: avAudioSession, queue: nil) { _ in
assert(!Thread.isMainThread)
self.updateIsSpeakerphoneEnabled()
}
@ -201,7 +201,7 @@ protocol CallAudioServiceDelegate: class {
private func updateIsSpeakerphoneEnabled() {
let value = avAudioSession.currentRoute.outputs.contains { (portDescription: AVAudioSessionPortDescription) -> Bool in
return portDescription.portName == AVAudioSessionPortBuiltInSpeaker
return portDescription.portType == .builtInSpeaker
}
DispatchQueue.main.async {
self.isSpeakerphoneEnabled = value
@ -213,8 +213,8 @@ protocol CallAudioServiceDelegate: class {
guard let call = call, !call.isTerminated else {
// Revert to default audio
setAudioSession(category: AVAudioSessionCategorySoloAmbient,
mode: AVAudioSessionModeDefault)
setAudioSession(category: .soloAmbient,
mode: .default)
return
}
@ -224,12 +224,12 @@ protocol CallAudioServiceDelegate: class {
// to setPreferredInput to call.audioSource.portDescription in this case,
// but in practice I'm seeing the call revert to the bluetooth headset.
// Presumably something else (in WebRTC?) is touching our shared AudioSession. - mjk
let options: AVAudioSessionCategoryOptions = call.audioSource?.isBuiltInEarPiece == true ? [] : [.allowBluetooth]
let options: AVAudioSession.CategoryOptions = call.audioSource?.isBuiltInEarPiece == true ? [] : [.allowBluetooth]
if call.state == .localRinging {
// SoloAmbient plays through speaker, but respects silent switch
setAudioSession(category: AVAudioSessionCategorySoloAmbient,
mode: AVAudioSessionModeDefault)
setAudioSession(category: .soloAmbient,
mode: .default)
} else if call.hasLocalVideo {
// Because ModeVideoChat affects gain, we don't want to apply it until the call is connected.
// otherwise sounds like ringing will be extra loud for video vs. speakerphone
@ -238,16 +238,16 @@ protocol CallAudioServiceDelegate: class {
// side effect of setting options: .allowBluetooth, when I remove the (seemingly unnecessary)
// option, and inspect AVAudioSession.sharedInstance.categoryOptions == 0. And availableInputs
// does not include my linked bluetooth device
setAudioSession(category: AVAudioSessionCategoryPlayAndRecord,
mode: AVAudioSessionModeVideoChat,
setAudioSession(category: .playAndRecord,
mode: .videoChat,
options: options)
} else {
// Apple Docs say that setting mode to AVAudioSessionModeVoiceChat has the
// side effect of setting options: .allowBluetooth, when I remove the (seemingly unnecessary)
// option, and inspect AVAudioSession.sharedInstance.categoryOptions == 0. And availableInputs
// does not include my linked bluetooth device
setAudioSession(category: AVAudioSessionCategoryPlayAndRecord,
mode: AVAudioSessionModeVoiceChat,
setAudioSession(category: .playAndRecord,
mode: .voiceChat,
options: options)
}
@ -384,7 +384,7 @@ protocol CallAudioServiceDelegate: class {
// Stop solo audio, revert to default.
isSpeakerphoneEnabled = false
setAudioSession(category: AVAudioSessionCategorySoloAmbient)
setAudioSession(category: .soloAmbient)
}
// MARK: Playing Sounds
@ -488,9 +488,9 @@ protocol CallAudioServiceDelegate: class {
return AudioSource(portDescription: portDescription)
}
private func setAudioSession(category: String,
mode: String? = nil,
options: AVAudioSessionCategoryOptions = AVAudioSessionCategoryOptions(rawValue: 0)) {
private func setAudioSession(category: AVAudioSession.Category,
mode: AVAudioSession.Mode? = nil,
options: AVAudioSession.CategoryOptions = AVAudioSession.CategoryOptions(rawValue: 0)) {
AssertIsOnMainThread()
@ -534,8 +534,7 @@ protocol CallAudioServiceDelegate: class {
if oldOptions != options {
Logger.debug("audio session changed options: \(oldOptions) -> \(options) ")
}
try avAudioSession.setCategory(category, with: options)
try avAudioSession.ows_setCategory(category, with: options)
}
} catch {
let message = "failed to set category: \(category) mode: \(String(describing: mode)), options: \(options) with error: \(error)"

@ -1831,7 +1831,7 @@ private class SignalCallData: NSObject {
func removeObserver(_ observer: CallServiceObserver) {
AssertIsOnMainThread()
while let index = observers.index(where: { $0.value === observer }) {
while let index = observers.firstIndex(where: { $0.value === observer }) {
observers.remove(at: index)
}
}

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -191,7 +191,7 @@ protocol CallObserver: class {
func removeObserver(_ observer: CallObserver) {
AssertIsOnMainThread()
while let index = observers.index(where: { $0.value === observer }) {
while let index = observers.firstIndex(where: { $0.value === observer }) {
observers.remove(at: index)
}
}

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
@ -102,7 +102,7 @@ final class CallKitCallManager: NSObject {
private(set) var calls = [SignalCall]()
func callWithLocalId(_ localId: UUID) -> SignalCall? {
guard let index = calls.index(where: { $0.localId == localId }) else {
guard let index = calls.firstIndex(where: { $0.localId == localId }) else {
return nil
}
return calls[index]
@ -124,7 +124,7 @@ final class CallKitCallManager: NSObject {
fileprivate extension Array {
mutating func removeFirst(where predicate: (Element) throws -> Bool) rethrows {
guard let index = try index(where: predicate) else {
guard let index = try firstIndex(where: predicate) else {
return
}

@ -60,7 +60,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
providerConfiguration.supportedHandleTypes = [.phoneNumber, .generic]
let iconMaskImage = #imageLiteral(resourceName: "logoSignal")
providerConfiguration.iconTemplateImageData = UIImagePNGRepresentation(iconMaskImage)
providerConfiguration.iconTemplateImageData = iconMaskImage.pngData()
// We don't set the ringtoneSound property, so that we use either the
// default iOS ringtone OR the custom ringtone associated with this user's

@ -120,7 +120,7 @@ import PromiseKit
public class func record(forFileUrl fileUrl: URL,
recordName: String) -> CKRecord {
let recordType = signalBackupRecordType
let recordID = CKRecordID(recordName: recordName)
let recordID = CKRecord.ID(recordName: recordName)
let record = CKRecord(recordType: recordType, recordID: recordID)
let asset = CKAsset(fileURL: fileUrl)
record[payloadKey] = asset
@ -234,7 +234,7 @@ import PromiseKit
success: @escaping () -> Void,
failure: @escaping (Error) -> Void) {
let recordIDs = recordNames.map { CKRecordID(recordName: $0) }
let recordIDs = recordNames.map { CKRecord.ID(recordName: $0) }
let deleteOperation = CKModifyRecordsOperation(recordsToSave: nil, recordIDsToDelete: recordIDs)
deleteOperation.modifyRecordsCompletionBlock = { (records, recordIds, error) in
@ -277,7 +277,7 @@ import PromiseKit
let (promise, resolver) = Promise<CKRecord?>.pending()
let recordId = CKRecordID(recordName: recordName)
let recordId = CKRecord.ID(recordName: recordName)
let fetchOperation = CKFetchRecordsOperation(recordIDs: [recordId ])
// Don't download the file; we're just using the fetch to check whether or
// not this record already exists.
@ -386,7 +386,7 @@ import PromiseKit
private class func fetchAllRecordNamesStep(recipientId: String?,
query: CKQuery,
previousRecordNames: [String],
cursor: CKQueryCursor?,
cursor: CKQueryOperation.Cursor?,
remainingRetries: Int,
success: @escaping ([String]) -> Void,
failure: @escaping (Error) -> Void) {
@ -484,17 +484,13 @@ import PromiseKit
}
public class func downloadDataFromCloud(recordName: String) -> Promise<Data> {
return downloadFromCloud(recordName: recordName,
remainingRetries: maxRetries)
.then { (asset) -> Promise<Data> in
do {
let data = try Data(contentsOf: asset.fileURL)
return Promise.value(data)
} catch {
Logger.error("couldn't load asset file: \(error).")
return Promise(error: invalidServiceResponseError())
.map { (asset) -> Data in
guard let fileURL = asset.fileURL else {
throw invalidServiceResponseError()
}
return try Data(contentsOf: fileURL)
}
}
@ -510,14 +506,11 @@ import PromiseKit
return downloadFromCloud(recordName: recordName,
remainingRetries: maxRetries)
.then { (asset) -> Promise<Void> in
do {
try FileManager.default.copyItem(at: asset.fileURL, to: toFileUrl)
return Promise.value(())
} catch {
Logger.error("couldn't copy asset file: \(error).")
return Promise(error: invalidServiceResponseError())
.done { asset in
guard let fileURL = asset.fileURL else {
throw invalidServiceResponseError()
}
try FileManager.default.copyItem(at: fileURL, to: toFileUrl)
}
}
@ -533,7 +526,7 @@ import PromiseKit
let (promise, resolver) = Promise<CKAsset>.pending()
let recordId = CKRecordID(recordName: recordName)
let recordId = CKRecord.ID(recordName: recordName)
let fetchOperation = CKFetchRecordsOperation(recordIDs: [recordId ])
// Download all keys for this record.
fetchOperation.perRecordCompletionBlock = { (record, recordId, error) in

@ -0,0 +1,22 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import <AVFoundation/AVAudioSession.h>
NS_ASSUME_NONNULL_BEGIN
@interface AVAudioSession (OWS)
// #RADAR 45397675 http://www.openradar.me/45397675
//
// A bug in Swift 4.2+ made `AVAudioSession#setCategory:categorywithOptions:error` not accessible
// to Swift.
//
// It's still available via ObjC, so we have an objc-category method which we can call from Swift
// which just calls the original `AVAudioSession#setCategory:categorywithOptions:error` method.
- (BOOL)ows_setCategory:(AVAudioSessionCategory)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(6.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);
@end
NS_ASSUME_NONNULL_END

@ -0,0 +1,15 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "AVAudioSession+OWS.h"
@implementation AVAudioSession(OWS)
- (BOOL)ows_setCategory:(AVAudioSessionCategory)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(6.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos)
{
return [self setCategory:category withOptions:options error:outError];
}
@end

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -26,7 +26,7 @@ public class AvatarTableViewCell: UITableViewCell {
}
@objc
public override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
self.avatarView = AvatarImageView()
avatarView.autoSetDimensions(to: CGSize(width: CGFloat(kStandardAvatarSize), height: CGFloat(kStandardAvatarSize)))

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
public protocol CaptionContainerViewDelegate: class {
@ -165,7 +165,7 @@ private class CaptionView: UIView {
override var intrinsicContentSize: CGSize {
var size = super.intrinsicContentSize
if size.height == UIViewNoIntrinsicMetric {
if size.height == UIView.noIntrinsicMetric {
size.height = layoutManager.usedRect(for: textContainer).height + textContainerInset.top + textContainerInset.bottom
}
size.height = min(kMaxHeight, size.height)

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
@ -21,7 +21,7 @@ class ContactCell: UITableViewCell {
var contact: Contact?
var showsWhenSelected: Bool = false
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
self.contactImageView = AvatarImageView()
self.textStackView = UIStackView()
self.titleLabel = UILabel()
@ -31,7 +31,7 @@ class ContactCell: UITableViewCell {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = UITableViewCellSelectionStyle.none
selectionStyle = UITableViewCell.SelectionStyle.none
textStackView.axis = .vertical
textStackView.addArrangedSubview(titleLabel)
@ -46,7 +46,7 @@ class ContactCell: UITableViewCell {
self.contentView.addSubview(contentColumns)
contentColumns.autoPinEdgesToSuperviewMargins()
NotificationCenter.default.addObserver(self, selector: #selector(self.didChangePreferredContentSize), name: NSNotification.Name.UIContentSizeCategoryDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.didChangePreferredContentSize), name: UIContentSizeCategory.didChangeNotification, object: nil)
}
required init?(coder aDecoder: NSCoder) {
@ -136,13 +136,13 @@ fileprivate extension CNContact {
let boldDescriptor = font.fontDescriptor.withSymbolicTraits(.traitBold)
let boldAttributes = [
NSAttributedStringKey.font: UIFont(descriptor: boldDescriptor!, size: 0)
NSAttributedString.Key.font: UIFont(descriptor: boldDescriptor!, size: 0)
]
if let attributedName = CNContactFormatter.attributedString(from: self, style: .fullName, defaultAttributes: nil) {
let highlightedName = attributedName.mutableCopy() as! NSMutableAttributedString
highlightedName.enumerateAttributes(in: NSRange(location: 0, length: highlightedName.length), options: [], using: { (attrs, range, _) in
if let property = attrs[NSAttributedStringKey(rawValue: CNContactPropertyAttribute)] as? String, property == keyToHighlight {
if let property = attrs[NSAttributedString.Key(rawValue: CNContactPropertyAttribute)] as? String, property == keyToHighlight {
highlightedName.addAttributes(boldAttributes, range: range)
}
})

@ -715,7 +715,7 @@ public class LinkPreviewView: UIStackView {
let activityIndicatorStyle: UIActivityIndicatorView.Style = (Theme.isDarkThemeEnabled
? .white
: .gray)
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: activityIndicatorStyle)
let activityIndicator = UIActivityIndicatorView(style: activityIndicatorStyle)
activityIndicator.startAnimating()
addArrangedSubview(activityIndicator)
let activityIndicatorSize: CGFloat = 25

@ -97,7 +97,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate {
Defaults to `UIViewAnimationOptionCurveEaseInOut`.
*/
open var animationCurve: UIViewAnimationCurve = .linear
open var animationCurve: UIView.AnimationCurve = .linear
/**
A boolean property that sets whether the `MarqueeLabel` should behave like a normal `UILabel`.
@ -245,7 +245,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate {
get {
switch speed {
case .duration(let duration): return duration
case .rate(_): return 0.0
case .rate: return 0.0
}
}
set {
@ -257,7 +257,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate {
@IBInspectable open var scrollRate: CGFloat {
get {
switch speed {
case .duration(_): return 0.0
case .duration: return 0.0
case .rate(let rate): return rate
}
}
@ -1050,7 +1050,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate {
let adjustedColors: [CGColor]
let trailingFadeNeeded = self.labelShouldScroll()
switch (type) {
switch type {
case .continuousReverse, .rightLeft:
adjustedColors = [(trailingFadeNeeded ? transparent : opaque), opaque, opaque, opaque]
@ -1074,7 +1074,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate {
let colorAnimation = GradientSetupAnimation(keyPath: "colors")
colorAnimation.fromValue = gradientMask.colors
colorAnimation.toValue = adjustedColors
colorAnimation.fillMode = kCAFillModeForwards
colorAnimation.fillMode = CAMediaTimingFillMode.forwards
colorAnimation.isRemovedOnCompletion = false
colorAnimation.delegate = self
gradientMask.add(colorAnimation, forKey: "setupFade")
@ -1088,25 +1088,24 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate {
self.layer.mask = nil
}
private func timingFunctionForAnimationCurve(_ curve: UIViewAnimationCurve) -> CAMediaTimingFunction {
let timingFunction: String?
private func timingFunctionForAnimationCurve(_ curve: UIView.AnimationCurve) -> CAMediaTimingFunction {
let timingFunction: CAMediaTimingFunctionName
switch curve {
case .easeIn:
timingFunction = kCAMediaTimingFunctionEaseIn
timingFunction = .easeIn
case .easeInOut:
timingFunction = kCAMediaTimingFunctionEaseInEaseOut
timingFunction = .easeInEaseOut
case .easeOut:
timingFunction = kCAMediaTimingFunctionEaseOut
timingFunction = .easeOut
default:
timingFunction = kCAMediaTimingFunctionLinear
timingFunction = .linear
}
return CAMediaTimingFunction(name: timingFunction!)
return CAMediaTimingFunction(name: timingFunction)
}
private func transactionDurationType(_ labelType: MarqueeType, interval: CGFloat, delay: CGFloat) -> TimeInterval {
switch (labelType) {
switch labelType {
case .leftRight, .rightLeft:
return TimeInterval(2.0 * (delay + interval))
default:
@ -1139,11 +1138,11 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate {
return CAReplicatorLayer.self
}
fileprivate weak var repliLayer: CAReplicatorLayer? {
fileprivate var repliLayer: CAReplicatorLayer? {
return self.layer as? CAReplicatorLayer
}
fileprivate weak var maskLayer: CAGradientLayer? {
fileprivate var maskLayer: CAGradientLayer? {
return self.layer.mask as! CAGradientLayer?
}
@ -1168,7 +1167,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate {
}
class fileprivate func notifyController(_ controller: UIViewController, message: MarqueeKeys) {
NotificationCenter.default.post(name: Notification.Name(rawValue: message.rawValue), object: nil, userInfo: ["controller" : controller])
NotificationCenter.default.post(name: Notification.Name(rawValue: message.rawValue), object: nil, userInfo: ["controller": controller])
}
@objc public func restartForViewController(_ notification: Notification) {
@ -1554,7 +1553,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate {
sublabel.tintColorDidChange()
}
override open var contentMode: UIViewContentMode {
override open var contentMode: UIView.ContentMode {
get {
return sublabel.contentMode
}
@ -1588,7 +1587,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate {
//
public protocol MarqueeStep {
var timeStep: CGFloat { get }
var timingFunction: UIViewAnimationCurve { get }
var timingFunction: UIView.AnimationCurve { get }
var edgeFades: EdgeFade { get }
}
@ -1626,7 +1625,7 @@ public struct ScrollStep: MarqueeStep {
- Note: The animation curve value for the first `ScrollStep` in a sequence has no effect.
*/
public let timingFunction: UIViewAnimationCurve
public let timingFunction: UIView.AnimationCurve
/**
The position of the label for this scroll step.
@ -1642,7 +1641,7 @@ public struct ScrollStep: MarqueeStep {
*/
public let edgeFades: EdgeFade
public init(timeStep: CGFloat, timingFunction: UIViewAnimationCurve = .linear, position: Position, edgeFades: EdgeFade) {
public init(timeStep: CGFloat, timingFunction: UIView.AnimationCurve = .linear, position: Position, edgeFades: EdgeFade) {
self.timeStep = timeStep
self.position = position
self.edgeFades = edgeFades
@ -1675,7 +1674,7 @@ public struct FadeStep: MarqueeStep {
/**
The animation curve to utilize between the previous fade state in a sequence and this step.
*/
public let timingFunction: UIViewAnimationCurve
public let timingFunction: UIView.AnimationCurve
/**
The option set defining the edge fade state for this fade step.
@ -1687,7 +1686,7 @@ public struct FadeStep: MarqueeStep {
*/
public let edgeFades: EdgeFade
public init(timeStep: CGFloat, timingFunction: UIViewAnimationCurve = .linear, edgeFades: EdgeFade) {
public init(timeStep: CGFloat, timingFunction: UIView.AnimationCurve = .linear, edgeFades: EdgeFade) {
self.timeStep = timeStep
self.timingFunction = timingFunction
self.edgeFades = edgeFades
@ -1705,8 +1704,8 @@ public struct EdgeFade: OptionSet {
}
// Define helpful typealiases
fileprivate typealias MLAnimationCompletionBlock = (_ finished: Bool) -> Void
fileprivate typealias MLAnimation = (anim: CAKeyframeAnimation, duration: CGFloat)
private typealias MLAnimationCompletionBlock = (_ finished: Bool) -> Void
private typealias MLAnimation = (anim: CAKeyframeAnimation, duration: CGFloat)
private class GradientSetupAnimation: CABasicAnimation {
}

@ -40,7 +40,7 @@ class QuotedReplyPreview: UIView, OWSQuotedMessageViewDelegate {
updateContents()
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: .UIContentSizeCategoryDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil)
}
private let draftMarginTop: CGFloat = 6

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -63,7 +63,7 @@ class ReminderView: UIView {
func setupSubviews() {
let textColor: UIColor
let iconColor: UIColor
switch (mode) {
switch mode {
case .nag:
self.backgroundColor = UIColor.ows_reminderYellow
textColor = UIColor.ows_gray90

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import XCTest
@ -36,12 +36,12 @@ final class ContactsPickerTest: SignalBaseTest {
let collatedContacts = contactsPicker.collatedContacts([emailOnlyContactB, emailOnlyContactD])
let sectionTitles = contactsPicker.collationForTests.sectionTitles
if let bIndex = sectionTitles.index(of: "B") {
if let bIndex = sectionTitles.firstIndex(of: "B") {
let bSectionContacts = collatedContacts[bIndex]
XCTAssertEqual(bSectionContacts.first, emailOnlyContactB)
}
if let dIndex = sectionTitles.index(of: "D") {
if let dIndex = sectionTitles.firstIndex(of: "D") {
let dSectionContacts = collatedContacts[dIndex]
XCTAssertEqual(dSectionContacts.first, emailOnlyContactD)
}
@ -58,7 +58,7 @@ final class ContactsPickerTest: SignalBaseTest {
let collatedContacts = contactsPicker.collatedContacts([nameAndEmailContact])
let sectionTitles = contactsPicker.collationForTests.sectionTitles
if let aIndex = sectionTitles.index(of: "A") {
if let aIndex = sectionTitles.firstIndex(of: "A") {
let aSectionContacts = collatedContacts[aIndex]
XCTAssertEqual(aSectionContacts.first, nameAndEmailContact)
}

@ -49,7 +49,7 @@ class ImageEditorTest: SignalBaseTest {
private func writeDummyImage() -> String {
let image = UIImage.init(color: .red, size: CGSize(width: 1, height: 1))
guard let data = UIImagePNGRepresentation(image) else {
guard let data = image.pngData() else {
owsFail("Couldn't export dummy image.")
}
let filePath = OWSFileSystem.temporaryFilePath(withFileExtension: "png")

@ -65,9 +65,11 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
self.mode = mode
let attachmentItems = attachments.map { SignalAttachmentItem(attachment: $0 )}
self.attachmentItemCollection = AttachmentItemCollection(attachmentItems: attachmentItems)
let options: [UIPageViewController.OptionsKey: Any] = [.interPageSpacing: kSpacingBetweenItems]
super.init(transitionStyle: .scroll,
navigationOrientation: .horizontal,
options: [UIPageViewControllerOptionInterPageSpacingKey: kSpacingBetweenItems])
options: options)
self.dataSource = self
self.delegate = self
@ -516,7 +518,7 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
return viewController
}
private func setCurrentItem(_ item: SignalAttachmentItem, direction: UIPageViewControllerNavigationDirection, animated isAnimated: Bool) {
private func setCurrentItem(_ item: SignalAttachmentItem, direction: UIPageViewController.NavigationDirection, animated isAnimated: Bool) {
guard let page = self.buildPage(item: item) else {
owsFailDebug("unexpectedly unable to build new page")
return
@ -586,10 +588,10 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
let isLossy: Bool = attachmentItem.attachment.mimeType.caseInsensitiveCompare(OWSMimeTypeImageJpeg) == .orderedSame
if isLossy {
dataUTI = kUTTypeJPEG as String
return UIImageJPEGRepresentation(dstImage, 0.9)
return dstImage.jpegData(compressionQuality: 0.9)
} else {
dataUTI = kUTTypePNG as String
return UIImagePNGRepresentation(dstImage)
return dstImage.pngData()
}
}() else {
owsFailDebug("Could not export for output.")
@ -620,7 +622,7 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
}
func attachmentItem(before currentItem: SignalAttachmentItem) -> SignalAttachmentItem? {
guard let currentIndex = attachmentItems.index(of: currentItem) else {
guard let currentIndex = attachmentItems.firstIndex(of: currentItem) else {
owsFailDebug("currentIndex was unexpectedly nil")
return nil
}
@ -635,7 +637,7 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
}
func attachmentItem(after currentItem: SignalAttachmentItem) -> SignalAttachmentItem? {
guard let currentIndex = attachmentItems.index(of: currentItem) else {
guard let currentIndex = attachmentItems.firstIndex(of: currentItem) else {
owsFailDebug("currentIndex was unexpectedly nil")
return nil
}
@ -747,17 +749,17 @@ extension AttachmentApprovalViewController: GalleryRailViewDelegate {
return
}
guard let currentIndex = attachmentItems.index(of: currentItem) else {
guard let currentIndex = attachmentItems.firstIndex(of: currentItem) else {
owsFailDebug("currentIndex was unexpectedly nil")
return
}
guard let targetIndex = attachmentItems.index(of: targetItem) else {
guard let targetIndex = attachmentItems.firstIndex(of: targetItem) else {
owsFailDebug("targetIndex was unexpectedly nil")
return
}
let direction: UIPageViewControllerNavigationDirection = currentIndex < targetIndex ? .forward : .reverse
let direction: UIPageViewController.NavigationDirection = currentIndex < targetIndex ? .forward : .reverse
self.setCurrentItem(targetItem, direction: direction, animated: true)
}

@ -103,7 +103,7 @@ class AttachmentCaptionViewController: OWSViewController {
let backgroundView = UIView()
backgroundView.backgroundColor = UIColor(white: 0, alpha: 0.5)
view.addSubview(backgroundView)
view.sendSubview(toBack: backgroundView)
view.sendSubviewToBack(backgroundView)
backgroundView.autoPinEdge(toSuperviewEdge: .leading)
backgroundView.autoPinEdge(toSuperviewEdge: .trailing)
backgroundView.autoPinEdge(toSuperviewEdge: .bottom)

@ -80,7 +80,7 @@ class AttachmentItemCollection {
}
func itemAfter(item: SignalAttachmentItem) -> SignalAttachmentItem? {
guard let currentIndex = attachmentItems.index(of: item) else {
guard let currentIndex = attachmentItems.firstIndex(of: item) else {
owsFailDebug("currentIndex was unexpectedly nil")
return nil
}
@ -91,7 +91,7 @@ class AttachmentItemCollection {
}
func itemBefore(item: SignalAttachmentItem) -> SignalAttachmentItem? {
guard let currentIndex = attachmentItems.index(of: item) else {
guard let currentIndex = attachmentItems.firstIndex(of: item) else {
owsFailDebug("currentIndex was unexpectedly nil")
return nil
}

@ -78,7 +78,7 @@ public class AttachmentPrepViewController: OWSViewController, PlayerProgressBarD
scrollView.showsVerticalScrollIndicator = false
// Panning should stop pretty soon after the user stops scrolling
scrollView.decelerationRate = UIScrollViewDecelerationRateFast
scrollView.decelerationRate = UIScrollView.DecelerationRate.fast
// We want scroll view content up and behind the system status bar content
// but we want other content (e.g. bar buttons) to respect the top layout guide.

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -138,8 +138,8 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
let audioPlayButton = UIButton()
self.audioPlayButton = audioPlayButton
setAudioIconToPlay()
audioPlayButton.imageView?.layer.minificationFilter = kCAFilterTrilinear
audioPlayButton.imageView?.layer.magnificationFilter = kCAFilterTrilinear
audioPlayButton.imageView?.layer.minificationFilter = .trilinear
audioPlayButton.imageView?.layer.magnificationFilter = .trilinear
audioPlayButton.addTarget(self, action: #selector(audioPlayButtonPressed), for: .touchUpInside)
let buttonSize = createHeroViewSize()
audioPlayButton.autoSetDimension(.width, toSize: buttonSize)
@ -221,8 +221,8 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
}
let imageView = UIImageView(image: image)
imageView.layer.minificationFilter = kCAFilterTrilinear
imageView.layer.magnificationFilter = kCAFilterTrilinear
imageView.layer.minificationFilter = .trilinear
imageView.layer.magnificationFilter = .trilinear
let aspectRatio = image.size.width / image.size.height
addSubviewWithScaleAspectFitLayout(view: imageView, aspectRatio: aspectRatio)
contentView = imageView
@ -243,8 +243,8 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
}
let imageView = UIImageView(image: image)
imageView.layer.minificationFilter = kCAFilterTrilinear
imageView.layer.magnificationFilter = kCAFilterTrilinear
imageView.layer.minificationFilter = .trilinear
imageView.layer.magnificationFilter = .trilinear
let aspectRatio = image.size.width / image.size.height
addSubviewWithScaleAspectFitLayout(view: imageView, aspectRatio: aspectRatio)
contentView = imageView
@ -307,8 +307,8 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
let image = UIImage(named: imageName)
assert(image != nil)
let imageView = UIImageView(image: image)
imageView.layer.minificationFilter = kCAFilterTrilinear
imageView.layer.magnificationFilter = kCAFilterTrilinear
imageView.layer.minificationFilter = .trilinear
imageView.layer.magnificationFilter = .trilinear
imageView.layer.shadowColor = UIColor.black.cgColor
let shadowScaling = 5.0
imageView.layer.shadowRadius = CGFloat(2.0 * shadowScaling)

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -74,7 +74,7 @@ public class ModalActivityIndicatorViewController: OWSViewController {
: UIColor(white: 0, alpha: 0.25))
self.view.isOpaque = false
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
self.activityIndicator = activityIndicator
self.view.addSubview(activityIndicator)
activityIndicator.autoCenterInSuperview()

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
@ -32,8 +32,8 @@ public class AvatarImageView: UIImageView {
func configureView() {
self.autoPinToSquareAspectRatio()
self.layer.minificationFilter = kCAFilterTrilinear
self.layer.magnificationFilter = kCAFilterTrilinear
self.layer.minificationFilter = .trilinear
self.layer.magnificationFilter = .trilinear
self.layer.masksToBounds = true
self.layer.addSublayer(self.shadowLayer)
@ -57,7 +57,7 @@ public class AvatarImageView: UIImageView {
// This can be any color since the fill should be clipped.
self.shadowLayer.fillColor = UIColor.black.cgColor
self.shadowLayer.path = shadowPath.cgPath
self.shadowLayer.fillRule = kCAFillRuleEvenOdd
self.shadowLayer.fillRule = .evenOdd
self.shadowLayer.shadowColor = (Theme.isDarkThemeEnabled ? UIColor.white : UIColor.black).cgColor
self.shadowLayer.shadowRadius = 0.5
self.shadowLayer.shadowOpacity = 0.15
@ -203,14 +203,14 @@ public class AvatarImageButton: UIButton {
// This can be any color since the fill should be clipped.
shadowLayer.fillColor = UIColor.black.cgColor
shadowLayer.path = shadowPath.cgPath
shadowLayer.fillRule = kCAFillRuleEvenOdd
shadowLayer.fillRule = .evenOdd
shadowLayer.shadowColor = (Theme.isDarkThemeEnabled ? UIColor.white : UIColor.black).cgColor
shadowLayer.shadowRadius = 0.5
shadowLayer.shadowOpacity = 0.15
shadowLayer.shadowOffset = .zero
}
override public func setImage(_ image: UIImage?, for state: UIControlState) {
override public func setImage(_ image: UIImage?, for state: UIControl.State) {
ensureViewConfigured()
super.setImage(image, for: state)
}
@ -226,8 +226,8 @@ public class AvatarImageButton: UIButton {
autoPinToSquareAspectRatio()
layer.minificationFilter = kCAFilterTrilinear
layer.magnificationFilter = kCAFilterTrilinear
layer.minificationFilter = .trilinear
layer.magnificationFilter = .trilinear
layer.masksToBounds = true
layer.addSublayer(shadowLayer)

@ -470,8 +470,8 @@ public class ImageEditorCanvasView: UIView {
shapeLayer.path = bezierPath.cgPath
shapeLayer.fillColor = nil
shapeLayer.lineCap = kCALineCapRound
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.lineCap = CAShapeLayerLineCap.round
shapeLayer.lineJoin = CAShapeLayerLineJoin.round
shapeLayer.zPosition = zPositionForItem(item: item, model: model, zPositionBase: brushLayerZ)
return shapeLayer
@ -503,8 +503,8 @@ public class ImageEditorCanvasView: UIView {
let text = item.text.filterForDisplay ?? ""
let attributedString = NSAttributedString(string: text,
attributes: [
NSAttributedStringKey.font: item.font.withSize(fontSize),
NSAttributedStringKey.foregroundColor: item.color.color
NSAttributedString.Key.font: item.font.withSize(fontSize),
NSAttributedString.Key.foregroundColor: item.color.color
])
let layer = EditorTextLayer(itemId: item.itemId)
layer.string = attributedString
@ -512,7 +512,7 @@ public class ImageEditorCanvasView: UIView {
layer.font = CGFont(item.font.fontName as CFString)
layer.fontSize = fontSize
layer.isWrapped = true
layer.alignmentMode = kCAAlignmentCenter
layer.alignmentMode = CATextLayerAlignmentMode.center
// I don't think we need to enable allowsFontSubpixelQuantization
// or set truncationMode.

@ -48,7 +48,7 @@ public class OWSNavigationBar: UINavigationBar {
applyTheme()
NotificationCenter.default.addObserver(self, selector: #selector(callDidChange), name: .OWSWindowManagerCallDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didChangeStatusBarFrame), name: .UIApplicationDidChangeStatusBarFrame, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didChangeStatusBarFrame), name: UIApplication.didChangeStatusBarFrameNotification, object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(themeDidChange),
name: .ThemeDidChange,
@ -75,7 +75,7 @@ public class OWSNavigationBar: UINavigationBar {
return
}
if UIAccessibilityIsReduceTransparencyEnabled() {
if UIAccessibility.isReduceTransparencyEnabled {
blurEffectView?.isHidden = true
let color = Theme.navbarBackgroundColor
let backgroundImage = UIImage(color: color)
@ -213,7 +213,7 @@ public class OWSNavigationBar: UINavigationBar {
respectsTheme = false
barStyle = .black
titleTextAttributes = [NSAttributedStringKey.foregroundColor: Theme.darkThemePrimaryColor]
titleTextAttributes = [NSAttributedString.Key.foregroundColor: Theme.darkThemePrimaryColor]
barTintColor = Theme.darkThemeBackgroundColor.withAlphaComponent(0.6)
tintColor = Theme.darkThemePrimaryColor

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -106,7 +106,7 @@ public class PlayerProgressBar: UIView {
// Background
backgroundColor = UIColor.lightGray.withAlphaComponent(0.5)
if !UIAccessibilityIsReduceTransparencyEnabled() {
if !UIAccessibility.isReduceTransparencyEnabled {
addSubview(blurEffectView)
blurEffectView.ows_autoPinToSuperviewEdges()
}

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -58,7 +58,7 @@ public class OWSVideoPlayer: NSObject {
if item.currentTime() == item.duration {
// Rewind for repeated plays, but only if it previously played to end.
avPlayer.seek(to: kCMTimeZero)
avPlayer.seek(to: CMTime.zero)
}
avPlayer.play()
@ -67,7 +67,7 @@ public class OWSVideoPlayer: NSObject {
@objc
public func stop() {
avPlayer.pause()
avPlayer.seek(to: kCMTimeZero)
avPlayer.seek(to: CMTime.zero)
audioSession.endAudioActivity(self.audioActivity)
}

@ -301,7 +301,7 @@ public class SignalAttachment: NSObject {
let asset = AVURLAsset(url: mediaUrl)
let generator = AVAssetImageGenerator(asset: asset)
generator.appliesPreferredTrackTransform = true
let cgImage = try generator.copyCGImage(at: CMTimeMake(0, 1), actualTime: nil)
let cgImage = try generator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
let image = UIImage(cgImage: cgImage)
cachedVideoPreview = image
@ -747,8 +747,7 @@ public class SignalAttachment: NSObject {
}
dstImage = resizedImage
}
guard let jpgImageData = UIImageJPEGRepresentation(dstImage,
jpegCompressionQuality(imageUploadQuality: imageUploadQuality)) else {
guard let jpgImageData = dstImage.jpegData(compressionQuality: jpegCompressionQuality(imageUploadQuality: imageUploadQuality)) else {
attachment.error = .couldNotConvertToJpeg
return attachment
}

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -39,7 +39,7 @@ public class OWSAudioSession: NSObject {
@objc
public func setup() {
NotificationCenter.default.addObserver(self, selector: #selector(proximitySensorStateDidChange(notification:)), name: .UIDeviceProximityStateDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(proximitySensorStateDidChange(notification:)), name: UIDevice.proximityStateDidChangeNotification, object: nil)
}
// MARK: Dependencies
@ -105,20 +105,20 @@ public class OWSAudioSession: NSObject {
// Eventually it would be nice to consolidate more of the audio
// session handling.
} else if aggregateBehaviors.contains(.playAndRecord) {
assert(avAudioSession.recordPermission() == .granted)
try avAudioSession.setCategory(AVAudioSessionCategoryRecord)
assert(avAudioSession.recordPermission == .granted)
try avAudioSession.setCategory(.record)
} else if aggregateBehaviors.contains(.audioMessagePlayback) {
if self.device.proximityState {
Logger.debug("proximityState: true")
try avAudioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
try avAudioSession.setCategory(.playAndRecord)
try avAudioSession.overrideOutputAudioPort(.none)
} else {
Logger.debug("proximityState: false")
try avAudioSession.setCategory(AVAudioSessionCategoryPlayback)
try avAudioSession.setCategory(.playback)
}
} else if aggregateBehaviors.contains(.playback) {
try avAudioSession.setCategory(AVAudioSessionCategoryPlayback)
try avAudioSession.setCategory(.playback)
} else {
ensureAudioSessionActivationStateAfterDelay()
}
@ -168,7 +168,7 @@ public class OWSAudioSession: NSObject {
do {
// When playing audio in Signal, other apps audio (e.g. Music) is paused.
// By notifying when we deactivate, the other app can resume playback.
try avAudioSession.setActive(false, with: [.notifyOthersOnDeactivation])
try avAudioSession.setActive(false, options: [.notifyOthersOnDeactivation])
} catch {
owsFailDebug("failed with error: \(error)")
}

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -72,7 +72,7 @@ public class ConversationStyle: NSObject {
NotificationCenter.default.addObserver(self,
selector: #selector(uiContentSizeCategoryDidChange),
name: NSNotification.Name.UIContentSizeCategoryDidChange,
name: UIContentSizeCategory.didChangeNotification,
object: nil)
}

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
@objc
@ -52,7 +52,7 @@ public class OWSProximityMonitoringManagerImpl: NSObject, OWSProximityMonitoring
@objc
public func setup() {
NotificationCenter.default.addObserver(self, selector: #selector(proximitySensorStateDidChange(notification:)), name: .UIDeviceProximityStateDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(proximitySensorStateDidChange(notification:)), name: UIDevice.proximityStateDidChangeNotification, object: nil)
}
@objc

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -50,7 +50,7 @@ public enum OWSMediaError: Error {
let generator = AVAssetImageGenerator(asset: asset)
generator.maximumSize = maxSize
generator.appliesPreferredTrackTransform = true
let time: CMTime = CMTimeMake(1, 60)
let time: CMTime = CMTimeMake(value: 1, timescale: 60)
let cgImage = try generator.copyCGImage(at: time, actualTime: nil)
let image = UIImage(cgImage: cgImage)
return image

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -164,7 +164,7 @@ private struct OWSThumbnailRequest {
} else {
throw OWSThumbnailError.assertionFailure(description: "Invalid attachment type.")
}
guard let thumbnailData = UIImageJPEGRepresentation(thumbnailImage, 0.85) else {
guard let thumbnailData = thumbnailImage.jpegData(compressionQuality: 0.85) else {
throw OWSThumbnailError.failure(description: "Could not convert thumbnail to JPEG.")
}
do {

@ -699,7 +699,7 @@ public class OWSLinkPreview: MTLModel {
let maxImageSize: CGFloat = 1024
let shouldResize = imageSize.width > maxImageSize || imageSize.height > maxImageSize
guard shouldResize else {
guard let dstData = UIImageJPEGRepresentation(srcImage, 0.8) else {
guard let dstData = srcImage.jpegData(compressionQuality: 0.8) else {
Logger.error("Could not write resized image.")
return Promise(error: LinkPreviewError.invalidContent)
}
@ -710,7 +710,7 @@ public class OWSLinkPreview: MTLModel {
Logger.error("Could not resize image.")
return Promise(error: LinkPreviewError.invalidContent)
}
guard let dstData = UIImageJPEGRepresentation(dstImage, 0.8) else {
guard let dstData = dstImage.jpegData(compressionQuality: 0.8) else {
Logger.error("Could not write resized image.")
return Promise(error: LinkPreviewError.invalidContent)
}

@ -41,7 +41,7 @@ public class LRUCache<KeyType: Hashable & Equatable, ValueType> {
NotificationCenter.default.addObserver(self,
selector: #selector(didReceiveMemoryWarning),
name: NSNotification.Name.UIApplicationDidReceiveMemoryWarning,
name: UIApplication.didReceiveMemoryWarningNotification,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(didEnterBackground),

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -10,9 +10,9 @@ public extension MessageSender {
/**
* Wrap message sending in a Promise for easier callback chaining.
*/
public func sendPromise(message: TSOutgoingMessage) -> Promise<Void> {
func sendPromise(message: TSOutgoingMessage) -> Promise<Void> {
let promise: Promise<Void> = Promise { resolver in
self.send(message, success: resolver.fulfill, failure: resolver.reject)
self.send(message, success: { resolver.fulfill(()) }, failure: resolver.reject)
}
// Ensure sends complete before they're GC'd.

@ -14,12 +14,12 @@ public extension YapDatabaseConnection {
func readWritePromise(_ block: @escaping (YapDatabaseReadWriteTransaction) -> Void) -> Promise<Void> {
return Promise { resolver in
self.asyncReadWrite(block, completionBlock: resolver.fulfill)
self.asyncReadWrite(block, completionBlock: { resolver.fulfill(()) })
}
}
func read(_ block: @escaping (YapDatabaseReadTransaction) throws -> Void) throws {
var errorToRaise: Error? = nil
var errorToRaise: Error?
read { transaction in
do {
@ -35,7 +35,7 @@ public extension YapDatabaseConnection {
}
func readWrite(_ block: @escaping (YapDatabaseReadWriteTransaction) throws -> Void) throws {
var errorToRaise: Error? = nil
var errorToRaise: Error?
readWrite { transaction in
do {

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
@ -63,7 +63,7 @@ class SAELoadViewController: UIViewController {
self.view.backgroundColor = UIColor.ows_signalBrandBlue
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
self.activityIndicator = activityIndicator
self.view.addSubview(activityIndicator)
activityIndicator.autoCenterInSuperview()

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
@ -23,7 +23,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
enum ShareViewControllerError: Error {
case assertionError(description: String)
case unsupportedMedia
case notRegistered()
case notRegistered
case obsoleteShare
}
@ -475,7 +475,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
// If root view is an error view, do nothing.
return
}
throw ShareViewControllerError.notRegistered()
throw ShareViewControllerError.notRegistered
}
// MARK: ShareViewDelegate, SAEFailedViewDelegate
@ -866,7 +866,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
isConvertibleToTextMessage: isConvertibleToTextMessage))
}
} else if let image = value as? UIImage {
if let data = UIImagePNGRepresentation(image) {
if let data = image.pngData() {
let tempFilePath = OWSFileSystem.temporaryFilePath(withFileExtension: "png")
do {
let url = NSURL.fileURL(withPath: tempFilePath)

Loading…
Cancel
Save