Merge branch 'charlesmchen/swift4'

This commit is contained in:
Matthew Chen 2018-05-30 15:28:56 -04:00
commit 295f720f93
80 changed files with 468 additions and 303 deletions

View file

@ -2593,12 +2593,12 @@
453518911FC63DBF00210559 = {
CreatedOnToolsVersion = 9.2;
DevelopmentTeam = U68MSDN6DR;
LastSwiftMigration = 0910;
LastSwiftMigration = 0930;
ProvisioningStyle = Automatic;
};
D221A088169C9E5E00537ABF = {
DevelopmentTeam = U68MSDN6DR;
LastSwiftMigration = 0800;
LastSwiftMigration = 0930;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.ApplicationGroups.iOS = {
@ -2629,7 +2629,7 @@
};
D221A0A9169C9E5F00537ABF = {
DevelopmentTeam = U68MSDN6DR;
LastSwiftMigration = 0800;
LastSwiftMigration = 0930;
ProvisioningStyle = Automatic;
TestTargetID = D221A088169C9E5E00537ABF;
};
@ -3539,6 +3539,7 @@
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "-fobjc-arc-exceptions";
SDKROOT = iphoneos;
SWIFT_VERSION = 4.0;
VALIDATE_PRODUCT = YES;
};
name = Test;
@ -3597,7 +3598,8 @@
SDKROOT = iphoneos;
SWIFT_OBJC_BRIDGING_HEADER = "Signal/src/Signal-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TEST_AFTER_BUILD = YES;
VALID_ARCHS = "arm64 armv7 armv7s";
WRAPPER_EXTENSION = app;
@ -3657,7 +3659,8 @@
PROVISIONING_PROFILE = "";
SWIFT_OBJC_BRIDGING_HEADER = "Signal/test/SignalTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Signal.app/Signal";
VALID_ARCHS = "arm64 armv7s armv7 i386 x86_64";
};
@ -3901,7 +3904,8 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -3978,7 +3982,8 @@
SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
@ -4055,7 +4060,8 @@
SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
@ -4128,6 +4134,7 @@
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "-fobjc-arc-exceptions";
SDKROOT = iphoneos;
SWIFT_VERSION = 4.0;
VALIDATE_PRODUCT = YES;
};
name = Debug;
@ -4196,6 +4203,7 @@
);
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.0;
VALIDATE_PRODUCT = YES;
};
name = "App Store Release";
@ -4254,7 +4262,8 @@
SDKROOT = iphoneos;
SWIFT_OBJC_BRIDGING_HEADER = "Signal/src/Signal-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TEST_AFTER_BUILD = YES;
VALID_ARCHS = "arm64 armv7 armv7s";
WRAPPER_EXTENSION = app;
@ -4313,7 +4322,8 @@
PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
SWIFT_OBJC_BRIDGING_HEADER = "Signal/src/Signal-Bridging-Header.h";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TEST_AFTER_BUILD = YES;
VALID_ARCHS = "arm64 armv7 armv7s";
WRAPPER_EXTENSION = app;
@ -4373,7 +4383,8 @@
PROVISIONING_PROFILE = "";
SWIFT_OBJC_BRIDGING_HEADER = "Signal/test/SignalTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUNDLE_LOADER)";
VALID_ARCHS = "arm64 armv7s armv7 i386 x86_64";
};
@ -4431,7 +4442,8 @@
PROVISIONING_PROFILE = "";
SWIFT_OBJC_BRIDGING_HEADER = "Signal/test/SignalTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUNDLE_LOADER)";
VALID_ARCHS = "arm64 armv7s armv7 i386 x86_64";
};

View file

@ -912,7 +912,7 @@ static NSTimeInterval launchStartedAt;
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(NSString *)identifier
forLocalNotification:(UILocalNotification *)notification
completionHandler:(void (^)(void))completionHandler
completionHandler:(void (^)())completionHandler
{
OWSAssertIsOnMainThread();
@ -939,7 +939,7 @@ static NSTimeInterval launchStartedAt;
handleActionWithIdentifier:(NSString *)identifier
forLocalNotification:(UILocalNotification *)notification
withResponseInfo:(NSDictionary *)responseInfo
completionHandler:(void (^)(void))completionHandler
completionHandler:(void (^)())completionHandler
{
OWSAssertIsOnMainThread();

View file

@ -7,7 +7,7 @@ import PromiseKit
import SignalServiceKit
@objc(OWSMessageFetcherJob)
class MessageFetcherJob: NSObject {
public class MessageFetcherJob: NSObject {
private var timer: Timer?
@ -16,7 +16,7 @@ class MessageFetcherJob: NSObject {
private let messageReceiver: OWSMessageReceiver
private let signalService: OWSSignalService
init(messageReceiver: OWSMessageReceiver, networkManager: TSNetworkManager, signalService: OWSSignalService) {
@objc public init(messageReceiver: OWSMessageReceiver, networkManager: TSNetworkManager, signalService: OWSSignalService) {
self.messageReceiver = messageReceiver
self.networkManager = networkManager
self.signalService = signalService
@ -58,7 +58,7 @@ class MessageFetcherJob: NSObject {
return promise
}
@objc func run() -> AnyPromise {
@objc public func run() -> AnyPromise {
return AnyPromise(run())
}

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -12,7 +12,7 @@ import SignalMessaging
* Syncing is accomplished via the existing contact syncing mechanism, except the only contact synced is ourself. It's incumbent on the linked device
* to treat this "self contact" record specially.
*/
@objc class MultiDeviceProfileKeyUpdateJob: NSObject {
@objc public class MultiDeviceProfileKeyUpdateJob: NSObject {
let TAG = "[MultiDeviceProfileKeyUpdateJob]"
@ -21,7 +21,7 @@ import SignalMessaging
let messageSender: MessageSender
let profileManager: OWSProfileManager
required init(profileKey: OWSAES256Key, identityManager: OWSIdentityManager, messageSender: MessageSender, profileManager: OWSProfileManager) {
@objc public required init(profileKey: OWSAES256Key, identityManager: OWSIdentityManager, messageSender: MessageSender, profileManager: OWSProfileManager) {
self.profileKey = profileKey
self.identityManager = identityManager
@ -29,7 +29,7 @@ import SignalMessaging
self.profileManager = profileManager
}
class func run(profileKey: OWSAES256Key, identityManager: OWSIdentityManager, messageSender: MessageSender, profileManager: OWSProfileManager) {
@objc public class func run(profileKey: OWSAES256Key, identityManager: OWSIdentityManager, messageSender: MessageSender, profileManager: OWSProfileManager) {
return self.init(profileKey: profileKey, identityManager: identityManager, messageSender: messageSender, profileManager: profileManager).run()
}

View file

@ -7,7 +7,7 @@ import PromiseKit
import SignalServiceKit
@objc(OWSSessionResetJob)
class SessionResetJob: NSObject {
public class SessionResetJob: NSObject {
let TAG = "SessionResetJob"
@ -16,7 +16,7 @@ class SessionResetJob: NSObject {
let primaryStorage: OWSPrimaryStorage
let messageSender: MessageSender
required init(recipientId: String, thread: TSThread, messageSender: MessageSender, primaryStorage: OWSPrimaryStorage) {
@objc public required init(recipientId: String, thread: TSThread, messageSender: MessageSender, primaryStorage: OWSPrimaryStorage) {
self.thread = thread
self.recipientId = recipientId
self.messageSender = messageSender
@ -64,7 +64,7 @@ class SessionResetJob: NSObject {
}
}
class func run(contactThread: TSContactThread, messageSender: MessageSender, primaryStorage: OWSPrimaryStorage) {
@objc public class func run(contactThread: TSContactThread, messageSender: MessageSender, primaryStorage: OWSPrimaryStorage) {
let job = self.init(recipientId: contactThread.contactIdentifier(),
thread: contactThread,
messageSender: messageSender,

View file

@ -18,8 +18,9 @@ class SyncPushTokensJob: NSObject {
return PushRegistrationManager.shared
}
var uploadOnlyIfStale = true
@objc var uploadOnlyIfStale = true
@objc
required init(accountManager: AccountManager, preferences: OWSPreferences) {
self.accountManager = accountManager
self.preferences = preferences

View file

@ -10,7 +10,8 @@ import SignalServiceKit
* Signal is actually two services - textSecure for messages and red phone (for calls).
* AccountManager delegates to both.
*/
class AccountManager: NSObject {
@objc
public class AccountManager: NSObject {
let TAG = "[AccountManager]"
let textSecureAccountManager: TSAccountManager
@ -22,7 +23,8 @@ class AccountManager: NSObject {
return PushManager.shared()
}
required init(textSecureAccountManager: TSAccountManager, preferences: OWSPreferences) {
@objc
public required init(textSecureAccountManager: TSAccountManager, preferences: OWSPreferences) {
self.networkManager = textSecureAccountManager.networkManager
self.textSecureAccountManager = textSecureAccountManager
self.preferences = preferences

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -20,6 +20,7 @@ class CompareSafetyNumbersActivity: UIActivity {
var mySafetyNumbers: String?
let delegate: CompareSafetyNumbersActivityDelegate
@objc
required init(delegate: CompareSafetyNumbersActivityDelegate) {
self.delegate = delegate
super.init()
@ -48,7 +49,7 @@ class CompareSafetyNumbersActivity: UIActivity {
}
override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
return stringsFrom(activityItems:activityItems).count > 0
return stringsFrom(activityItems: activityItems).count > 0
}
override func prepare(withActivityItems activityItems: [Any]) {
@ -73,7 +74,7 @@ class CompareSafetyNumbersActivity: UIActivity {
if pasteboardSafetyNumbers == mySafetyNumbers {
Logger.info("\(TAG) successfully matched safety numbers. local numbers: \(String(describing: mySafetyNumbers)) pasteboard:\(pasteboardSafetyNumbers)")
delegate.compareSafetyNumbersActivitySucceeded(activity:self)
delegate.compareSafetyNumbersActivitySucceeded(activity: self)
} else {
Logger.warn("\(TAG) local numbers: \(String(describing: mySafetyNumbers)) didn't match pasteboard:\(pasteboardSafetyNumbers)")
let error = OWSErrorWithCodeDescription(OWSErrorCode.privacyVerificationFailure,
@ -91,7 +92,7 @@ class CompareSafetyNumbersActivity: UIActivity {
var numericOnly: String?
if let regex = try? NSRegularExpression(pattern: "\\D", options: .caseInsensitive) {
numericOnly = regex.stringByReplacingMatches(in: string!, options: .withTransparentBounds, range: NSMakeRange(0, string!.count), withTemplate: "")
numericOnly = regex.stringByReplacingMatches(in: string!, options: .withTransparentBounds, range: NSRange(location: 0, length: string!.count), withTemplate: "")
}
return numericOnly

View file

@ -4,13 +4,13 @@
import Foundation
extension UIApplication {
@objc public extension UIApplication {
var frontmostViewControllerIgnoringAlerts: UIViewController? {
@objc public var frontmostViewControllerIgnoringAlerts: UIViewController? {
return findFrontmostViewController(ignoringAlerts: true)
}
var frontmostViewController: UIViewController? {
@objc public var frontmostViewController: UIViewController? {
return findFrontmostViewController(ignoringAlerts: false)
}
@ -26,7 +26,7 @@ extension UIApplication {
return viewController.findFrontmostViewController(ignoringAlerts)
}
func openSystemSettings() {
@objc public func openSystemSettings() {
openURL(URL(string: UIApplicationOpenSettingsURLString)!)
}

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -9,6 +9,7 @@ extension UIStoryboard {
case main = "Main"
}
@objc
class var main: UIStoryboard {
return UIStoryboard(name: StoryboardName.main.rawValue, bundle: Bundle.main)
}

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -8,7 +8,7 @@ import Foundation
* Present call related notifications to the user.
*/
@objc(OWSCallNotificationsAdapter)
class CallNotificationsAdapter: NSObject {
public class CallNotificationsAdapter: NSObject {
let TAG = "[CallNotificationsAdapter]"
let adaptee: OWSCallNotificationsAdaptee

View file

@ -150,7 +150,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
NotificationCenter.default.removeObserver(self)
}
func didBecomeActive() {
@objc func didBecomeActive() {
if (self.isViewLoaded) {
shouldRemoteVideoControlsBeHidden = false
}
@ -235,7 +235,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
createSettingsNagViews()
}
func didTouchRootView(sender: UIGestureRecognizer) {
@objc func didTouchRootView(sender: UIGestureRecognizer) {
if !remoteVideoView.isHidden {
shouldRemoteVideoControlsBeHidden = !shouldRemoteVideoControlsBeHidden
}
@ -541,7 +541,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
contactAvatarView.autoPinEdge(toSuperviewEdge: .right, withInset: 0, relation: .greaterThanOrEqual)
contactAvatarView.autoPinEdge(toSuperviewEdge: .bottom, withInset: 0, relation: .greaterThanOrEqual)
contactAvatarView.autoPinEdge(toSuperviewEdge: .left, withInset: 0, relation: .greaterThanOrEqual)
NSLayoutConstraint.autoSetPriority(UILayoutPriorityDefaultLow) {
NSLayoutConstraint.autoSetPriority(UILayoutPriority.defaultLow) {
contactAvatarView.autoPinEdgesToSuperviewMargins()
}
@ -825,7 +825,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
/**
* Ends a connected call. Do not confuse with `didPressDeclineCall`.
*/
func didPressHangup(sender: UIButton) {
@objc func didPressHangup(sender: UIButton) {
Logger.info("\(TAG) called \(#function)")
callUIAdapter.localHangupCall(call)
@ -833,14 +833,14 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
dismissIfPossible(shouldDelay: false)
}
func didPressMute(sender muteButton: UIButton) {
@objc func didPressMute(sender muteButton: UIButton) {
Logger.info("\(TAG) called \(#function)")
muteButton.isSelected = !muteButton.isSelected
callUIAdapter.setIsMuted(call: call, isMuted: muteButton.isSelected)
}
func didPressAudioSource(sender button: UIButton) {
@objc func didPressAudioSource(sender button: UIButton) {
Logger.info("\(TAG) called \(#function)")
if self.hasAlternateAudioSources {
@ -863,20 +863,20 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
dismissIfPossible(shouldDelay: false)
}
func didPressAnswerCall(sender: UIButton) {
@objc func didPressAnswerCall(sender: UIButton) {
Logger.info("\(TAG) called \(#function)")
callUIAdapter.answerCall(call)
}
func didPressVideo(sender: UIButton) {
@objc func didPressVideo(sender: UIButton) {
Logger.info("\(TAG) called \(#function)")
let hasLocalVideo = !sender.isSelected
callUIAdapter.setHasLocalVideo(call: call, hasLocalVideo: hasLocalVideo)
}
func didPressFlipCamera(sender: UIButton) {
@objc func didPressFlipCamera(sender: UIButton) {
// toggle value
sender.isSelected = !sender.isSelected
@ -889,7 +889,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
/**
* Denies an incoming not-yet-connected call, Do not confuse with `didPressHangup`.
*/
func didPressDeclineCall(sender: UIButton) {
@objc func didPressDeclineCall(sender: UIButton) {
Logger.info("\(TAG) called \(#function)")
callUIAdapter.declineCall(call)
@ -897,7 +897,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
dismissIfPossible(shouldDelay: false)
}
func didPressShowCallSettings(sender: UIButton) {
@objc func didPressShowCallSettings(sender: UIButton) {
Logger.info("\(TAG) called \(#function)")
markSettingsNagAsComplete()
@ -916,7 +916,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
})
}
func didPressDismissNag(sender: UIButton) {
@objc func didPressDismissNag(sender: UIButton) {
Logger.info("\(TAG) called \(#function)")
markSettingsNagAsComplete()
@ -939,7 +939,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
preferences.setIsCallKitPrivacyEnabled(preferences.isCallKitPrivacyEnabled())
}
func didTapLeaveCall(sender: UIButton) {
@objc func didTapLeaveCall(sender: UIButton) {
OWSWindowManager.shared().leaveCallView()
}

View file

@ -15,10 +15,12 @@ public protocol ContactShareViewHelperDelegate: class {
@objc
public class ContactShareViewHelper: NSObject, CNContactViewControllerDelegate {
@objc
weak var delegate: ContactShareViewHelperDelegate?
let contactsManager: OWSContactsManager
@objc
public required init(contactsManager: OWSContactsManager) {
SwiftAssertIsOnMainThread(#function)
@ -89,6 +91,7 @@ public class ContactShareViewHelper: NSObject, CNContactViewControllerDelegate {
inviteFlow.sendSMSTo(phoneNumbers: phoneNumbers)
}
@objc
func showAddToContacts(contactShare: ContactShareViewModel, fromViewController: UIViewController) {
Logger.info("\(logTag) \(#function)")

View file

@ -48,6 +48,7 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate {
fatalError("Unimplemented")
}
@objc
required init(contactShare: ContactShareViewModel) {
contactsManager = Environment.current().contactsManager
self.contactShare = contactShare
@ -214,7 +215,7 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate {
// Back Button
let backButtonSize = CGFloat(50)
let backButton = TappableView(actionBlock: { [weak self] _ in
let backButton = TappableView(actionBlock: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.didPressDismiss()
})
@ -280,21 +281,21 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate {
stackView.addArrangedSubview(createCircleActionButton(text: NSLocalizedString("ACTION_SEND_MESSAGE",
comment: "Label for 'sent message' button in contact view."),
imageName: "contact_view_message",
actionBlock: { [weak self] _ in
actionBlock: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.didPressSendMessage()
}))
stackView.addArrangedSubview(createCircleActionButton(text: NSLocalizedString("ACTION_AUDIO_CALL",
comment: "Label for 'audio call' button in contact view."),
imageName: "contact_view_audio_call",
actionBlock: { [weak self] _ in
actionBlock: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.didPressAudioCall()
}))
stackView.addArrangedSubview(createCircleActionButton(text: NSLocalizedString("ACTION_VIDEO_CALL",
comment: "Label for 'video call' button in contact view."),
imageName: "contact_view_video_call",
actionBlock: { [weak self] _ in
actionBlock: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.didPressVideoCall()
}))
@ -307,7 +308,7 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate {
// Show invite button for system contacts without a Signal account.
let inviteButton = createLargePillButton(text: NSLocalizedString("ACTION_INVITE",
comment: "Label for 'invite' button in contact view."),
actionBlock: { [weak self] _ in
actionBlock: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.didPressInvite()
})
@ -334,7 +335,7 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate {
// Always show "add to contacts" button.
let addToContactsButton = createLargePillButton(text: NSLocalizedString("CONVERSATION_VIEW_ADD_TO_CONTACTS_OFFER",
comment: "Message shown in conversation view that offers to add an unknown user to your phone's contacts."),
actionBlock: { [weak self] _ in
actionBlock: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.didPressAddToContacts()
})
@ -373,7 +374,7 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate {
for phoneNumber in contactShare.phoneNumbers {
rows.append(ContactFieldView.contactFieldView(forPhoneNumber: phoneNumber,
layoutMargins: UIEdgeInsets(top: 5, left: hMargin, bottom: 5, right: hMargin),
actionBlock: { [weak self] _ in
actionBlock: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.didPressPhoneNumber(phoneNumber: phoneNumber)
}))
@ -382,7 +383,7 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate {
for email in contactShare.emails {
rows.append(ContactFieldView.contactFieldView(forEmail: email,
layoutMargins: UIEdgeInsets(top: 5, left: hMargin, bottom: 5, right: hMargin),
actionBlock: { [weak self] _ in
actionBlock: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.didPressEmail(email: email)
}))
@ -391,7 +392,7 @@ class ContactViewController: OWSViewController, ContactShareViewHelperDelegate {
for address in contactShare.addresses {
rows.append(ContactFieldView.contactFieldView(forAddress: address,
layoutMargins: UIEdgeInsets(top: 5, left: hMargin, bottom: 5, right: hMargin),
actionBlock: { [weak self] _ in
actionBlock: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.didPressAddress(address: address)
}))

View file

@ -59,6 +59,11 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
}
private let collation = UILocalizedIndexedCollation.current()
public var collationForTests: UILocalizedIndexedCollation {
get {
return collation
}
}
private let contactStore = CNContactStore()
// Data Source State
@ -67,6 +72,7 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
private lazy var selectedContacts = [Contact]()
// Configuration
@objc
public weak var contactsPickerDelegate: ContactsPickerDelegate?
private let subtitleCellType: SubtitleCellValue
private let allowsMultipleSelection: Bool
@ -300,11 +306,11 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView
// MARK: - Button Actions
func onTouchCancelButton() {
@objc func onTouchCancelButton() {
contactsPickerDelegate?.contactsPickerDidCancel(self)
}
func onTouchDoneButton() {
@objc func onTouchDoneButton() {
contactsPickerDelegate?.contactsPicker(self, didSelectMultipleContacts: selectedContacts)
}

View file

@ -12,8 +12,10 @@ public protocol ConversationHeaderViewDelegate {
@objc
public class ConversationHeaderView: UIStackView {
@objc
public weak var delegate: ConversationHeaderViewDelegate?
@objc
public var attributedTitle: NSAttributedString? {
get {
return self.titleLabel.attributedText
@ -23,6 +25,7 @@ public class ConversationHeaderView: UIStackView {
}
}
@objc
public var attributedSubtitle: NSAttributedString? {
get {
return self.subtitleLabel.attributedText
@ -41,14 +44,18 @@ public class ConversationHeaderView: UIStackView {
}
}
@objc
public let titlePrimaryFont: UIFont = UIFont.ows_boldFont(withSize: 17)
@objc
public let titleSecondaryFont: UIFont = UIFont.ows_regularFont(withSize: 9)
@objc
public let subtitleFont: UIFont = UIFont.ows_regularFont(withSize: 12)
private let titleLabel: UILabel
private let subtitleLabel: UILabel
private let avatarView: AvatarImageView
@objc
public required init(thread: TSThread, contactsManager: OWSContactsManager) {
let avatarView = ConversationAvatarImageView(thread: thread, diameter: 36, contactsManager: contactsManager)
@ -110,7 +117,7 @@ public class ConversationHeaderView: UIStackView {
// MARK: Delegate Methods
func didTapView(tapGesture: UITapGestureRecognizer) {
@objc func didTapView(tapGesture: UITapGestureRecognizer) {
guard tapGesture.state == .recognized else {
return
}

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -52,7 +52,7 @@ class OWSLayerView: UIView {
// region b) the rectangle at which the src image should be rendered
// given a dst view or output context that will yield the
// appropriate cropping.
class CropScaleImageViewController: OWSViewController {
@objc class CropScaleImageViewController: OWSViewController {
let TAG = "[CropScaleImageViewController]"
@ -71,7 +71,7 @@ class CropScaleImageViewController: OWSViewController {
//
// TODO: We could make this a parameter.
var dstSizePixels: CGSize {
return CGSize(width:210, height:210)
return CGSize(width: 210, height: 210)
}
var dstAspectRatio: CGFloat {
return dstSizePixels.width / dstSizePixels.height
@ -107,7 +107,7 @@ class CropScaleImageViewController: OWSViewController {
fatalError("\(#function) is unimplemented.")
}
required init(srcImage: UIImage, successCompletion : @escaping (UIImage) -> Void) {
@objc required init(srcImage: UIImage, successCompletion : @escaping (UIImage) -> Void) {
// normalized() can be slightly expensive but in practice this is fine.
self.srcImage = srcImage.normalized()
self.successCompletion = successCompletion
@ -136,13 +136,13 @@ class CropScaleImageViewController: OWSViewController {
// The "default" (no scaling, no translation) crop frame, expressed in
// srcImage's coordinate system.
srcDefaultCropSizePoints = defaultCropSizePoints(dstSizePoints:unitSquareSize)
srcDefaultCropSizePoints = defaultCropSizePoints(dstSizePoints: unitSquareSize)
assert(srcImageSizePoints.width >= srcDefaultCropSizePoints.width)
assert(srcImageSizePoints.height >= srcDefaultCropSizePoints.height)
// By default, center the crop region in the src image.
srcTranslation = CGPoint(x:(srcImageSizePoints.width - srcDefaultCropSizePoints.width) * 0.5,
y:(srcImageSizePoints.height - srcDefaultCropSizePoints.height) * 0.5)
srcTranslation = CGPoint(x: (srcImageSizePoints.width - srcDefaultCropSizePoints.width) * 0.5,
y: (srcImageSizePoints.height - srcDefaultCropSizePoints.height) * 0.5)
}
// Given a dst size, find the size of the largest crop region
@ -182,7 +182,7 @@ class CropScaleImageViewController: OWSViewController {
self.view.addSubview(contentView)
contentView.autoPinEdgesToSuperviewEdges()
let imageView = OWSLayerView(frame:CGRect.zero, layoutCallback: {[weak self] _ in
let imageView = OWSLayerView(frame: CGRect.zero, layoutCallback: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.updateImageLayout()
})
@ -205,7 +205,7 @@ class CropScaleImageViewController: OWSViewController {
}
let path = UIBezierPath(rect: bounds)
let circleRect = strongSelf.cropFrame(forBounds:bounds)
let circleRect = strongSelf.cropFrame(forBounds: bounds)
let radius = circleRect.size.width * 0.5
let circlePath = UIBezierPath(roundedRect: circleRect, cornerRadius: radius)
@ -222,13 +222,13 @@ class CropScaleImageViewController: OWSViewController {
let titleLabel = UILabel()
titleLabel.textColor = UIColor.white
titleLabel.textAlignment = .center
titleLabel.font = UIFont.ows_mediumFont(withSize:ScaleFromIPhone5(16))
titleLabel.font = UIFont.ows_mediumFont(withSize: ScaleFromIPhone5(16))
titleLabel.text = NSLocalizedString("CROP_SCALE_IMAGE_VIEW_TITLE",
comment: "Title for the 'crop/scale image' dialog.")
contentView.addSubview(titleLabel)
titleLabel.autoPinWidthToSuperview()
let titleLabelMargin = ScaleFromIPhone5(16)
titleLabel.autoPin(toTopLayoutGuideOf:self, withInset:titleLabelMargin)
titleLabel.autoPin(toTopLayoutGuideOf: self, withInset: titleLabelMargin)
createButtonRow(contentView: contentView)
@ -286,7 +286,7 @@ class CropScaleImageViewController: OWSViewController {
assert(defaultCropOriginPoints.y >= 0)
assert(defaultCropOriginPoints.x <= imageSizePoints.width - defaultCropSizePoints.width)
assert(defaultCropOriginPoints.y <= imageSizePoints.height - defaultCropSizePoints.height)
return CGRect(origin:defaultCropOriginPoints, size:defaultCropSizePoints)
return CGRect(origin: defaultCropOriginPoints, size: defaultCropSizePoints)
}
// Updates the image view _AND_ normalizes the current scale/translate state.
@ -308,19 +308,19 @@ class CropScaleImageViewController: OWSViewController {
return
}
// The frame of the crop circle within the image view.
let cropFrame = self.cropFrame(forBounds:CGRect(origin:CGPoint.zero, size: imageViewSizePoints))
let cropFrame = self.cropFrame(forBounds: CGRect(origin: CGPoint.zero, size: imageViewSizePoints))
// Normalize the scaling property.
imageScale = max(kMinImageScale, min(kMaxImageScale, imageScale))
let srcCropSizePoints = CGSize(width:srcDefaultCropSizePoints.width / imageScale,
height:srcDefaultCropSizePoints.height / imageScale)
let srcCropSizePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
let minSrcTranslationPoints = CGPoint.zero
// Prevent panning outside of image area.
let maxSrcTranslationPoints = CGPoint(x:srcImageSizePoints.width - srcCropSizePoints.width,
y:srcImageSizePoints.height - srcCropSizePoints.height
let maxSrcTranslationPoints = CGPoint(x: srcImageSizePoints.width - srcCropSizePoints.width,
y: srcImageSizePoints.height - srcCropSizePoints.height
)
// Normalize the translation property
@ -352,15 +352,15 @@ class CropScaleImageViewController: OWSViewController {
// output will be WYSIWYG with the view state.
private func imageRenderRect(forDstSize dstSize: CGSize) -> CGRect {
let srcCropSizePoints = CGSize(width:srcDefaultCropSizePoints.width / imageScale,
height:srcDefaultCropSizePoints.height / imageScale)
let srcCropSizePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
let srcToViewRatio = dstSize.width / srcCropSizePoints.width
return CGRect(origin: CGPoint(x:srcTranslation.x * -srcToViewRatio,
y:srcTranslation.y * -srcToViewRatio),
size: CGSize(width:srcImageSizePoints.width * +srcToViewRatio,
height:srcImageSizePoints.height * +srcToViewRatio
return CGRect(origin: CGPoint(x: srcTranslation.x * -srcToViewRatio,
y: srcTranslation.y * -srcToViewRatio),
size: CGSize(width: srcImageSizePoints.width * +srcToViewRatio,
height: srcImageSizePoints.height * +srcToViewRatio
))
}
@ -369,7 +369,7 @@ class CropScaleImageViewController: OWSViewController {
var lastPinchLocation: CGPoint = CGPoint.zero
var lastPinchScale: CGFloat = 1.0
func handlePinch(sender: UIPinchGestureRecognizer) {
@objc func handlePinch(sender: UIPinchGestureRecognizer) {
switch (sender.state) {
case .possible:
break
@ -388,11 +388,11 @@ class CropScaleImageViewController: OWSViewController {
let scaleDiff = sender.scale / lastPinchScale
// Update scaling.
let srcCropSizeBeforeScalePoints = CGSize(width:srcDefaultCropSizePoints.width / imageScale,
height:srcDefaultCropSizePoints.height / imageScale)
let srcCropSizeBeforeScalePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
imageScale = max(kMinImageScale, min(kMaxImageScale, imageScale * scaleDiff))
let srcCropSizeAfterScalePoints = CGSize(width:srcDefaultCropSizePoints.width / imageScale,
height:srcDefaultCropSizePoints.height / imageScale)
let srcCropSizeAfterScalePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
// Since the translation state reflects the "upper left" corner of the crop region, we need to
// adjust the translation when scaling to preserve the "center" of the crop region.
srcTranslation.x += (srcCropSizeBeforeScalePoints.width - srcCropSizeAfterScalePoints.width) * 0.5
@ -400,16 +400,16 @@ class CropScaleImageViewController: OWSViewController {
// Update translation.
let viewSizePoints = imageView.frame.size
let srcCropSizePoints = CGSize(width:srcDefaultCropSizePoints.width / imageScale,
height:srcDefaultCropSizePoints.height / imageScale)
let srcCropSizePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
let viewToSrcRatio = srcCropSizePoints.width / viewSizePoints.width
let gestureTranslation = CGPoint(x:location.x - lastPinchLocation.x,
y:location.y - lastPinchLocation.y)
let gestureTranslation = CGPoint(x: location.x - lastPinchLocation.x,
y: location.y - lastPinchLocation.y)
srcTranslation = CGPoint(x:srcTranslation.x + gestureTranslation.x * -viewToSrcRatio,
y:srcTranslation.y + gestureTranslation.y * -viewToSrcRatio)
srcTranslation = CGPoint(x: srcTranslation.x + gestureTranslation.x * -viewToSrcRatio,
y: srcTranslation.y + gestureTranslation.y * -viewToSrcRatio)
lastPinchLocation = location
lastPinchScale = sender.scale
@ -426,7 +426,7 @@ class CropScaleImageViewController: OWSViewController {
var srcTranslationAtPanStart: CGPoint = CGPoint.zero
func handlePan(sender: UIPanGestureRecognizer) {
@objc func handlePan(sender: UIPanGestureRecognizer) {
switch (sender.state) {
case .possible:
break
@ -435,8 +435,8 @@ class CropScaleImageViewController: OWSViewController {
break
case .changed, .ended:
let viewSizePoints = imageView.frame.size
let srcCropSizePoints = CGSize(width:srcDefaultCropSizePoints.width / imageScale,
height:srcDefaultCropSizePoints.height / imageScale)
let srcCropSizePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
let viewToSrcRatio = srcCropSizePoints.width / viewSizePoints.width
@ -444,8 +444,8 @@ class CropScaleImageViewController: OWSViewController {
sender.translation(in: sender.view)
// Update translation.
srcTranslation = CGPoint(x:srcTranslationAtPanStart.x + gestureTranslation.x * -viewToSrcRatio,
y:srcTranslationAtPanStart.y + gestureTranslation.y * -viewToSrcRatio)
srcTranslation = CGPoint(x: srcTranslationAtPanStart.x + gestureTranslation.x * -viewToSrcRatio,
y: srcTranslationAtPanStart.y + gestureTranslation.y * -viewToSrcRatio)
break
case .cancelled, .failed:
srcTranslation
@ -463,47 +463,47 @@ class CropScaleImageViewController: OWSViewController {
let buttonRow = UIView()
self.view.addSubview(buttonRow)
buttonRow.autoPinWidthToSuperview()
buttonRow.autoPinEdge(toSuperviewEdge:.bottom, withInset:buttonBottomMargin)
buttonRow.autoPinEdge(.top, to:.bottom, of:contentView, withOffset:buttonTopMargin)
buttonRow.autoPinEdge(toSuperviewEdge: .bottom, withInset: buttonBottomMargin)
buttonRow.autoPinEdge(.top, to: .bottom, of: contentView, withOffset: buttonTopMargin)
let cancelButton = createButton(title: CommonStrings.cancelButton,
action: #selector(cancelPressed))
buttonRow.addSubview(cancelButton)
cancelButton.autoPinEdge(toSuperviewEdge:.top)
cancelButton.autoPinEdge(toSuperviewEdge:.bottom)
cancelButton.autoPinEdge(toSuperviewEdge: .top)
cancelButton.autoPinEdge(toSuperviewEdge: .bottom)
cancelButton.autoPinEdge(toSuperviewEdge: .left)
let doneButton = createButton(title: NSLocalizedString("BUTTON_DONE",
comment: "Label for generic done button."),
action: #selector(donePressed))
buttonRow.addSubview(doneButton)
doneButton.autoPinEdge(toSuperviewEdge:.top)
doneButton.autoPinEdge(toSuperviewEdge:.bottom)
doneButton.autoPinEdge(toSuperviewEdge: .top)
doneButton.autoPinEdge(toSuperviewEdge: .bottom)
doneButton.autoPinEdge(toSuperviewEdge: .right)
}
private func createButton(title: String, action: Selector) -> UIButton {
let buttonFont = UIFont.ows_mediumFont(withSize:ScaleFromIPhone5To7Plus(18, 22))
let buttonFont = UIFont.ows_mediumFont(withSize: ScaleFromIPhone5To7Plus(18, 22))
let buttonWidth = ScaleFromIPhone5To7Plus(110, 140)
let buttonHeight = ScaleFromIPhone5To7Plus(35, 45)
let button = UIButton()
button.setTitle(title, for:.normal)
button.setTitleColor(UIColor.white, for:.normal)
button.setTitle(title, for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel!.font = buttonFont
button.addTarget(self, action:action, for:.touchUpInside)
button.autoSetDimension(.width, toSize:buttonWidth)
button.autoSetDimension(.height, toSize:buttonHeight)
button.addTarget(self, action: action, for: .touchUpInside)
button.autoSetDimension(.width, toSize: buttonWidth)
button.autoSetDimension(.height, toSize: buttonHeight)
return button
}
// MARK: - Event Handlers
func cancelPressed(sender: UIButton) {
dismiss(animated: true, completion:nil)
@objc func cancelPressed(sender: UIButton) {
dismiss(animated: true, completion: nil)
}
func donePressed(sender: UIButton) {
@objc func donePressed(sender: UIButton) {
let successCompletion = self.successCompletion
dismiss(animated: true, completion: {
guard let dstImage = self.generateDstImage() else {

View file

@ -2,7 +2,7 @@
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
class DebugUIFileBrowser: OWSTableViewController {
@objc class DebugUIFileBrowser: OWSTableViewController {
// MARK: Dependencies
var fileManager: FileManager {
@ -12,7 +12,7 @@ class DebugUIFileBrowser: OWSTableViewController {
// MARK: Overrides
let fileURL: URL
init(fileURL: URL) {
@objc init(fileURL: URL) {
self.fileURL = fileURL
super.init(nibName: nil, bundle: nil)
@ -125,7 +125,7 @@ class DebugUIFileBrowser: OWSTableViewController {
preferredStyle: .alert)
alert.addAction(OWSAlerts.cancelAction)
alert.addAction(UIAlertAction(title:"Rename \(strongSelf.fileURL.lastPathComponent)", style:.default) { _ in
alert.addAction(UIAlertAction(title: "Rename \(strongSelf.fileURL.lastPathComponent)", style: .default) { _ in
guard let textField = alert.textFields?.first else {
owsFail("missing text field")
return
@ -170,7 +170,7 @@ class DebugUIFileBrowser: OWSTableViewController {
preferredStyle: .alert)
alert.addAction(OWSAlerts.cancelAction)
alert.addAction(UIAlertAction(title:"Moving \(filename)", style:.default) { _ in
alert.addAction(UIAlertAction(title: "Moving \(filename)", style: .default) { _ in
guard let textField = alert.textFields?.first else {
owsFail("missing text field")
return
@ -259,7 +259,7 @@ class DebugUIFileBrowser: OWSTableViewController {
let protections: [FileProtectionType] = [.none, .complete, .completeUnlessOpen, .completeUntilFirstUserAuthentication]
protections.forEach { (protection: FileProtectionType) in
actionSheet.addAction(UIAlertAction(title: "\(protection.rawValue.replacingOccurrences(of:"NSFile", with: ""))", style: .default) { (_: UIAlertAction) in
actionSheet.addAction(UIAlertAction(title: "\(protection.rawValue.replacingOccurrences(of: "NSFile", with: ""))", style: .default) { (_: UIAlertAction) in
Logger.debug("\(strongSelf.logTag) chose protection: \(protection) for file: \(fileURL)")
let fileAttributes: [FileAttributeKey: Any] = [.protectionKey: protection]
do {
@ -288,7 +288,7 @@ class DebugUIFileBrowser: OWSTableViewController {
preferredStyle: .alert)
alert.addAction(OWSAlerts.cancelAction)
alert.addAction(UIAlertAction(title:"Create", style:.default) { _ in
alert.addAction(UIAlertAction(title: "Create", style: .default) { _ in
guard let textField = alert.textFields?.first else {
owsFail("missing text field")
return
@ -326,7 +326,7 @@ class DebugUIFileBrowser: OWSTableViewController {
preferredStyle: .alert)
alert.addAction(OWSAlerts.cancelAction)
alert.addAction(UIAlertAction(title:"Create", style:.default) { _ in
alert.addAction(UIAlertAction(title: "Create", style: .default) { _ in
guard let textField = alert.textFields?.first else {
owsFail("missing text field")
return

View file

@ -103,7 +103,7 @@ private class IntroducingCustomNotificationAudioExperienceUpgradeViewController:
return button
}
func didTapButton(sender: UIButton) {
@objc func didTapButton(sender: UIButton) {
Logger.debug("\(TAG) in \(#function)")
guard let buttonAction = self.buttonAction else {
@ -213,7 +213,7 @@ private class IntroductingReadReceiptsExperienceUpgradeViewController: Experienc
return button
}
func didTapButton(sender: UIButton) {
@objc func didTapButton(sender: UIButton) {
Logger.debug("\(TAG) in \(#function)")
guard let buttonAction = self.buttonAction else {
@ -343,7 +343,7 @@ private class IntroductingProfilesExperienceUpgradeViewController: ExperienceUpg
// MARK: - Actions
func didTapButton(sender: UIButton) {
@objc func didTapButton(sender: UIButton) {
Logger.debug("\(TAG) in \(#function)")
// dismiss the modally presented view controller, then proceed.
@ -382,7 +382,7 @@ private class CallKitExperienceUpgradeViewController: ExperienceUpgradeViewContr
// MARK: - Actions
func didTapPrivacySettingsButton(sender: UIButton) {
@objc func didTapPrivacySettingsButton(sender: UIButton) {
Logger.debug("\(TAG) in \(#function)")
// dismiss the modally presented view controller, then proceed.
@ -480,7 +480,8 @@ func setPageControlAppearance() {
pageControl.currentPageIndicatorTintColor = UIColor.ows_materialBlue
}
class ExperienceUpgradesPageViewController: OWSViewController, UIPageViewControllerDataSource {
@objc
public class ExperienceUpgradesPageViewController: OWSViewController, UIPageViewControllerDataSource {
let TAG = "[ExperienceUpgradeViewController]"
@ -494,7 +495,8 @@ class ExperienceUpgradesPageViewController: OWSViewController, UIPageViewControl
// MARK: - Initializers
required init(experienceUpgrades: [ExperienceUpgrade]) {
@objc
public required init(experienceUpgrades: [ExperienceUpgrade]) {
self.experienceUpgrades = experienceUpgrades
setPageControlAppearance()
@ -507,13 +509,14 @@ class ExperienceUpgradesPageViewController: OWSViewController, UIPageViewControl
}
@available(*, unavailable, message:"unavailable, use initWithExperienceUpgrade instead")
required init?(coder aDecoder: NSCoder) {
@objc
public required init?(coder aDecoder: NSCoder) {
fatalError("unimplemented")
}
// MARK: - View lifecycle
override func viewDidLoad() {
@objc public override func viewDidLoad() {
guard let firstViewController = allViewControllers.first else {
owsFail("\(TAG) no pages to show.")
dismiss(animated: true)
@ -524,7 +527,7 @@ class ExperienceUpgradesPageViewController: OWSViewController, UIPageViewControl
self.pageViewController.setViewControllers([ firstViewController ], direction: .forward, animated: false, completion: nil)
}
override func loadView() {
@objc public override func loadView() {
self.view = UIView.container()
view.backgroundColor = UIColor.white
@ -677,7 +680,7 @@ class ExperienceUpgradesPageViewController: OWSViewController, UIPageViewControl
allViewControllers.append(viewController)
}
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
@objc public override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
// Blocking write before dismiss, to be sure they're marked as complete
// before HomeView.didAppear is re-fired.
self.editingDBConnection.readWrite { transaction in
@ -687,12 +690,12 @@ class ExperienceUpgradesPageViewController: OWSViewController, UIPageViewControl
super.dismiss(animated: flag, completion: completion)
}
func didTapDismissButton(sender: UIButton) {
@objc func didTapDismissButton(sender: UIButton) {
Logger.debug("\(TAG) in \(#function)")
self.dismiss(animated: true)
}
func handleDismissGesture(sender: AnyObject) {
@objc func handleDismissGesture(sender: AnyObject) {
Logger.debug("\(TAG) in \(#function)")
self.dismiss(animated: true)
}

View file

@ -33,6 +33,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
var lastQuery: String = ""
@objc
public weak var delegate: GifPickerViewControllerDelegate?
let thread: TSThread
@ -60,6 +61,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
fatalError("\(#function) is unimplemented.")
}
@objc
required init(thread: TSThread, messageSender: MessageSender) {
self.thread = thread
self.messageSender = messageSender
@ -79,7 +81,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
progressiveSearchTimer?.invalidate()
}
func didBecomeActive() {
@objc func didBecomeActive() {
SwiftAssertIsOnMainThread(#function)
Logger.info("\(self.TAG) \(#function)")
@ -88,7 +90,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
ensureCellState()
}
func reachabilityChanged() {
@objc func reachabilityChanged() {
SwiftAssertIsOnMainThread(#function)
Logger.info("\(self.TAG) \(#function)")
@ -418,7 +420,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
// MARK: - Event Handlers
func donePressed(sender: UIButton) {
@objc func donePressed(sender: UIButton) {
dismiss(animated: true, completion: nil)
}
@ -505,7 +507,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect
// MARK: - Event Handlers
func retryTapped(sender: UIGestureRecognizer) {
@objc func retryTapped(sender: UIGestureRecognizer) {
guard sender.state == .recognized else {
return
}

View file

@ -19,12 +19,15 @@ class InviteFlow: NSObject, MFMessageComposeViewControllerDelegate, MFMailCompos
let installUrl = "https://signal.org/install/"
let homepageUrl = "https://signal.org"
@objc
let actionSheetController: UIAlertController
@objc
let presentingViewController: UIViewController
let contactsManager: OWSContactsManager
var channel: Channel?
@objc
required init(presentingViewController: UIViewController, contactsManager: OWSContactsManager) {
self.presentingViewController = presentingViewController
self.contactsManager = contactsManager
@ -165,6 +168,7 @@ class InviteFlow: NSObject, MFMessageComposeViewControllerDelegate, MFMailCompos
}
}
@objc
public func sendSMSTo(phoneNumbers: [String]) {
if #available(iOS 10.0, *) {
// iOS10 message compose view doesn't respect some system appearence attributes.

View file

@ -24,6 +24,7 @@ public class LongTextViewController: OWSViewController {
fatalError("\(#function) is unimplemented.")
}
@objc
public required init(viewItem: ConversationViewItem) {
self.viewItem = viewItem
@ -76,7 +77,7 @@ public class LongTextViewController: OWSViewController {
view.addSubview(messageTextView)
messageTextView.autoPinEdge(toSuperviewEdge: .leading)
messageTextView.autoPinEdge(toSuperviewEdge: .trailing)
messageTextView.textContainerInset = UIEdgeInsetsMake(0, view.layoutMargins.left, 0, view.layoutMargins.right)
messageTextView.textContainerInset = UIEdgeInsets(top: 0, left: view.layoutMargins.left, bottom: 0, right: view.layoutMargins.right)
messageTextView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
let footer = UIToolbar()
@ -95,7 +96,7 @@ public class LongTextViewController: OWSViewController {
// MARK: - Actions
func shareButtonPressed() {
@objc func shareButtonPressed() {
AttachmentSharing.showShareUI(forText: messageBody)
}
}

View file

@ -203,6 +203,7 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
Logger.debug("\(logTag) deinit")
}
@objc
init(thread: TSThread, uiDatabaseConnection: YapDatabaseConnection, options: MediaGalleryOption = []) {
self.thread = thread
assert(uiDatabaseConnection.isInLongLivedReadTransaction())
@ -277,6 +278,7 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
// TODO rename to replacingOriginRect
private var originRect: CGRect?
@objc
public func presentDetailView(fromViewController: UIViewController, mediaMessage: TSMessage, replacingView: UIView) {
var galleryItem: MediaGalleryItem?
uiDatabaseConnection.read { transaction in
@ -397,6 +399,7 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
// e.g. the conversation settings view controller
var fromNavController: OWSNavigationController?
@objc
func pushTileView(fromNavController: OWSNavigationController) {
var mostRecentItem: MediaGalleryItem?
self.uiDatabaseConnection.read { transaction in

View file

@ -13,6 +13,7 @@ public class GalleryItemBox: NSObject {
self.value = value
}
@objc
public var attachmentStream: TSAttachmentStream {
return value.attachmentStream
}

View file

@ -49,6 +49,7 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
fatalError("\(#function) is unimplemented.")
}
@objc
required init(viewItem: ConversationViewItem, message: TSMessage, mode: MessageMetadataViewMode) {
self.contactsManager = Environment.current().contactsManager
self.viewItem = viewItem
@ -496,7 +497,7 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
// MARK: - Actions
func shareButtonPressed() {
@objc func shareButtonPressed() {
guard let attachmentStream = attachmentStream else {
Logger.error("\(logTag) Share button should only be shown with attachment, but no attachment found.")
return
@ -525,7 +526,7 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
}
}
internal func yapDatabaseModified(notification: NSNotification) {
@objc internal func yapDatabaseModified(notification: NSNotification) {
SwiftAssertIsOnMainThread(#function)
guard !wasDeleted else {

View file

@ -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 = [NSFontAttributeName: pinEntryView.boldLabelFont]
let attributes = [NSAttributedStringKey.font: pinEntryView.boldLabelFont]
let attributedInstructionsText = NSAttributedString(string: instructionsTextHeader, attributes: attributes).rtlSafeAppend(" ", referenceView: pinEntryView).rtlSafeAppend(instructionsTextBody, referenceView: pinEntryView)

View file

@ -5,7 +5,8 @@
import Foundation
import SignalServiceKit
class SafetyNumberConfirmationAlert: NSObject {
@objc
public class SafetyNumberConfirmationAlert: NSObject {
let TAG = "[SafetyNumberConfirmationAlert]"
@ -17,18 +18,22 @@ class SafetyNumberConfirmationAlert: NSObject {
self.primaryStorage = OWSPrimaryStorage.shared()
}
@objc
public class func presentAlertIfNecessary(recipientId: String, confirmationText: String, contactsManager: OWSContactsManager, completion: @escaping (Bool) -> Void) -> Bool {
return self.presentAlertIfNecessary(recipientIds: [recipientId], confirmationText: confirmationText, contactsManager: contactsManager, completion: completion, beforePresentationHandler: nil)
}
@objc
public class func presentAlertIfNecessary(recipientId: String, confirmationText: String, contactsManager: OWSContactsManager, completion: @escaping (Bool) -> Void, beforePresentationHandler: (() -> Void)? = nil) -> Bool {
return self.presentAlertIfNecessary(recipientIds: [recipientId], confirmationText: confirmationText, contactsManager: contactsManager, completion: completion, beforePresentationHandler: beforePresentationHandler)
}
@objc
public class func presentAlertIfNecessary(recipientIds: [String], confirmationText: String, contactsManager: OWSContactsManager, completion: @escaping (Bool) -> Void) -> Bool {
return self.presentAlertIfNecessary(recipientIds: recipientIds, confirmationText: confirmationText, contactsManager: contactsManager, completion: completion, beforePresentationHandler: nil)
}
@objc
public class func presentAlertIfNecessary(recipientIds: [String], confirmationText: String, contactsManager: OWSContactsManager, completion: @escaping (Bool) -> Void, beforePresentationHandler: (() -> Void)? = nil) -> Bool {
return SafetyNumberConfirmationAlert(contactsManager: contactsManager).presentIfNecessary(recipientIds: recipientIds,
confirmationText: confirmationText,

View file

@ -6,7 +6,7 @@ import Foundation
import SignalServiceKit
import SignalMessaging
@objc enum MessageReceiptStatus: Int {
@objc public enum MessageReceiptStatus: Int {
case uploading
case sending
case sent
@ -25,7 +25,8 @@ public class MessageRecipientStatusUtils: NSObject {
}
// This method is per-recipient.
class func recipientStatus(outgoingMessage: TSOutgoingMessage,
@objc
public class func recipientStatus(outgoingMessage: TSOutgoingMessage,
recipientState: TSOutgoingMessageRecipientState,
referenceView: UIView) -> MessageReceiptStatus {
let (messageReceiptStatus, _, _) = recipientStatusAndStatusMessage(outgoingMessage: outgoingMessage,
@ -143,6 +144,7 @@ public class MessageRecipientStatusUtils: NSObject {
}
// This method is per-message.
@objc
public class func receiptMessage(outgoingMessage: TSOutgoingMessage,
referenceView: UIView) -> String {
let (_, message ) = receiptStatusAndMessage(outgoingMessage: outgoingMessage,
@ -151,7 +153,8 @@ public class MessageRecipientStatusUtils: NSObject {
}
// This method is per-message.
class func recipientStatus(outgoingMessage: TSOutgoingMessage, referenceView: UIView) -> MessageReceiptStatus {
@objc
public class func recipientStatus(outgoingMessage: TSOutgoingMessage, referenceView: UIView) -> MessageReceiptStatus {
let (status, _ ) = receiptStatusAndMessage(outgoingMessage: outgoingMessage,
referenceView: referenceView)
return status

View file

@ -6,21 +6,22 @@ import Foundation
@objc
public class ThreadViewModel: NSObject {
let hasUnreadMessages: Bool
let lastMessageDate: Date
let isGroupThread: Bool
let threadRecord: TSThread
let unreadCount: UInt
let contactIdentifier: String?
let name: String
let isMuted: Bool
@objc public let hasUnreadMessages: Bool
@objc public let lastMessageDate: Date
@objc public let isGroupThread: Bool
@objc public let threadRecord: TSThread
@objc public let unreadCount: UInt
@objc public let contactIdentifier: String?
@objc public let name: String
@objc public let isMuted: Bool
var isContactThread: Bool {
return !isGroupThread
}
let lastMessageText: String?
@objc public let lastMessageText: String?
init(thread: TSThread, transaction: YapDatabaseReadTransaction) {
@objc
public init(thread: TSThread, transaction: YapDatabaseReadTransaction) {
self.threadRecord = thread
self.lastMessageDate = thread.lastMessageDate()
self.isGroupThread = thread.isGroupThread()

View file

@ -71,7 +71,7 @@ import SignalMessaging
* --[SS.Hangup]-->
*/
enum CallError: Error {
public enum CallError: Error {
case providerReset
case assertionError(description: String)
case disconnected
@ -154,17 +154,23 @@ private class SignalCallData: NSObject {
let (callConnectedPromise, fulfillCallConnectedPromise, rejectCallConnectedPromise) = Promise<Void>.pending()
self.callConnectedPromise = callConnectedPromise
self.fulfillCallConnectedPromise = fulfillCallConnectedPromise
self.fulfillCallConnectedPromise = {
fulfillCallConnectedPromise(())
}
self.rejectCallConnectedPromise = rejectCallConnectedPromise
let (peerConnectionClientPromise, fulfillPeerConnectionClientPromise, rejectPeerConnectionClientPromise) = Promise<Void>.pending()
self.peerConnectionClientPromise = peerConnectionClientPromise
self.fulfillPeerConnectionClientPromise = fulfillPeerConnectionClientPromise
self.fulfillPeerConnectionClientPromise = {
fulfillPeerConnectionClientPromise(())
}
self.rejectPeerConnectionClientPromise = rejectPeerConnectionClientPromise
let (readyToSendIceUpdatesPromise, fulfillReadyToSendIceUpdatesPromise, rejectReadyToSendIceUpdatesPromise) = Promise<Void>.pending()
self.readyToSendIceUpdatesPromise = readyToSendIceUpdatesPromise
self.fulfillReadyToSendIceUpdatesPromise = fulfillReadyToSendIceUpdatesPromise
self.fulfillReadyToSendIceUpdatesPromise = {
fulfillReadyToSendIceUpdatesPromise(())
}
self.rejectReadyToSendIceUpdatesPromise = rejectReadyToSendIceUpdatesPromise
super.init()
@ -201,7 +207,7 @@ private class SignalCallData: NSObject {
}
// This class' state should only be accessed on the main queue.
@objc class CallService: NSObject, CallObserver, PeerConnectionClientDelegate {
@objc public class CallService: NSObject, CallObserver, PeerConnectionClientDelegate {
// MARK: - Properties
@ -216,7 +222,7 @@ private class SignalCallData: NSObject {
// Exposed by environment.m
internal let notificationsAdapter: CallNotificationsAdapter
internal var callUIAdapter: CallUIAdapter!
@objc public var callUIAdapter: CallUIAdapter!
// MARK: Class
@ -253,6 +259,7 @@ private class SignalCallData: NSObject {
}
}
@objc
var call: SignalCall? {
get {
SwiftAssertIsOnMainThread(#function)
@ -292,7 +299,7 @@ private class SignalCallData: NSObject {
}
}
required init(accountManager: AccountManager, contactsManager: OWSContactsManager, messageSender: MessageSender, notificationsAdapter: CallNotificationsAdapter) {
@objc public required init(accountManager: AccountManager, contactsManager: OWSContactsManager, messageSender: MessageSender, notificationsAdapter: CallNotificationsAdapter) {
self.accountManager = accountManager
self.contactsManager = contactsManager
self.messageSender = messageSender
@ -319,12 +326,12 @@ private class SignalCallData: NSObject {
NotificationCenter.default.removeObserver(self)
}
func didEnterBackground() {
@objc func didEnterBackground() {
SwiftAssertIsOnMainThread(#function)
self.updateIsVideoEnabled()
}
func didBecomeActive() {
@objc func didBecomeActive() {
SwiftAssertIsOnMainThread(#function)
self.updateIsVideoEnabled()
}
@ -332,7 +339,7 @@ private class SignalCallData: NSObject {
/**
* Choose whether to use CallKit or a Notification backed interface for calling.
*/
public func createCallUIAdapter() {
@objc public func createCallUIAdapter() {
SwiftAssertIsOnMainThread(#function)
if self.call != nil {
@ -347,7 +354,7 @@ private class SignalCallData: NSObject {
/**
* Initiate an outgoing call.
*/
public func handleOutgoingCall(_ call: SignalCall) -> Promise<Void> {
func handleOutgoingCall(_ call: SignalCall) -> Promise<Void> {
SwiftAssertIsOnMainThread(#function)
guard self.call == nil else {
@ -932,7 +939,7 @@ private class SignalCallData: NSObject {
*
* Used by notification actions which can't serialize a call object.
*/
public func handleAnswerCall(localId: UUID) {
@objc public func handleAnswerCall(localId: UUID) {
SwiftAssertIsOnMainThread(#function)
guard let call = self.call else {
@ -1245,6 +1252,7 @@ private class SignalCallData: NSObject {
}
}
@objc
func handleCallKitStartVideo() {
SwiftAssertIsOnMainThread(#function)
@ -1498,7 +1506,6 @@ private class SignalCallData: NSObject {
default:
assert(failedCall.callRecord != nil)
}
// It's essential to set call.state before terminateCall, because terminateCall nils self.call
failedCall.error = error

View file

@ -9,13 +9,13 @@ import SignalMessaging
/**
* Creates an outbound call via WebRTC.
*/
@objc class OutboundCallInitiator: NSObject {
@objc public class OutboundCallInitiator: NSObject {
let TAG = "[OutboundCallInitiator]"
let contactsManager: OWSContactsManager
let contactsUpdater: ContactsUpdater
init(contactsManager: OWSContactsManager, contactsUpdater: ContactsUpdater) {
@objc public init(contactsManager: OWSContactsManager, contactsUpdater: ContactsUpdater) {
self.contactsManager = contactsManager
self.contactsUpdater = contactsUpdater
@ -27,7 +27,7 @@ import SignalMessaging
/**
* |handle| is a user formatted phone number, e.g. from a system contacts entry
*/
public func initiateCall(handle: String) -> Bool {
@objc public func initiateCall(handle: String) -> Bool {
Logger.info("\(TAG) in \(#function) with handle: \(handle)")
guard let recipientId = PhoneNumber(fromE164: handle)?.toE164() else {
@ -41,7 +41,7 @@ import SignalMessaging
/**
* |recipientId| is a e164 formatted phone number.
*/
public func initiateCall(recipientId: String,
@objc public func initiateCall(recipientId: String,
isVideo: Bool) -> Bool {
// Rather than an init-assigned dependency property, we access `callUIAdapter` via Environment
// because it can change after app launch due to user settings

View file

@ -545,7 +545,7 @@ class PeerConnectionClient: NSObject, RTCPeerConnectionDelegate, RTCDataChannelD
if let error = error {
reject(error)
} else {
fulfill()
fulfill(())
}
})
}
@ -575,7 +575,7 @@ class PeerConnectionClient: NSObject, RTCPeerConnectionDelegate, RTCDataChannelD
reject(error)
return
}
fulfill()
fulfill(())
})
}
@ -616,7 +616,7 @@ class PeerConnectionClient: NSObject, RTCPeerConnectionDelegate, RTCDataChannelD
reject(error)
return
}
fulfill()
fulfill(())
})
}
return promise

View file

@ -5,7 +5,7 @@
import Foundation
import SignalServiceKit
enum CallState: String {
public enum CallState: String {
case idle
case dialing
case answering
@ -37,11 +37,13 @@ protocol CallObserver: class {
*
* This class' state should only be accessed on the main queue.
*/
@objc class SignalCall: NSObject {
@objc public class SignalCall: NSObject {
let TAG = "[SignalCall]"
var observers = [Weak<CallObserver>]()
@objc
let remotePhoneNumber: String
var isTerminated: Bool {
@ -59,6 +61,7 @@ protocol CallObserver: class {
let direction: CallDirection
// Distinguishes between calls locally, e.g. in CallKit
@objc
let localId: UUID
let thread: TSContactThread

View file

@ -19,6 +19,8 @@ final class CallKitCallManager: NSObject {
let callController = CXCallController()
let showNamesOnCallScreen: Bool
@objc
static let kAnonymousCallHandlePrefix = "Signal:"
required init(showNamesOnCallScreen: Bool) {

View file

@ -82,7 +82,7 @@ extension CallUIAdaptee {
* Notify the user of call related activities.
* Driven by either a CallKit or System notifications adaptee
*/
@objc class CallUIAdapter: NSObject, CallServiceObserver {
@objc public class CallUIAdapter: NSObject, CallServiceObserver {
let TAG = "[CallUIAdapter]"
private let adaptee: CallUIAdaptee
@ -90,7 +90,7 @@ extension CallUIAdaptee {
internal let audioService: CallAudioService
internal let callService: CallService
required init(callService: CallService, contactsManager: OWSContactsManager, notificationsAdapter: CallNotificationsAdapter) {
public required init(callService: CallService, contactsManager: OWSContactsManager, notificationsAdapter: CallNotificationsAdapter) {
SwiftAssertIsOnMainThread(#function)
self.contactsManager = contactsManager
@ -155,7 +155,7 @@ extension CallUIAdaptee {
return call
}
internal func answerCall(localId: UUID) {
@objc public func answerCall(localId: UUID) {
SwiftAssertIsOnMainThread(#function)
adaptee.answerCall(localId: localId)
@ -167,7 +167,7 @@ extension CallUIAdaptee {
adaptee.answerCall(call)
}
internal func declineCall(localId: UUID) {
@objc public func declineCall(localId: UUID) {
SwiftAssertIsOnMainThread(#function)
adaptee.declineCall(localId: localId)
@ -187,7 +187,7 @@ extension CallUIAdaptee {
}
}
internal func startAndShowOutgoingCall(recipientId: String, hasLocalVideo: Bool) {
@objc public func startAndShowOutgoingCall(recipientId: String, hasLocalVideo: Bool) {
SwiftAssertIsOnMainThread(#function)
adaptee.startAndShowOutgoingCall(recipientId: recipientId, hasLocalVideo: hasLocalVideo)

View file

@ -7,7 +7,7 @@ import SignalServiceKit
import SignalMessaging
@objc(OWSWebRTCCallMessageHandler)
class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler {
public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler {
// MARK - Properties
@ -21,7 +21,7 @@ class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler {
// MARK: Initializers
required init(accountManager: AccountManager, callService: CallService, messageSender: MessageSender) {
@objc public required init(accountManager: AccountManager, callService: CallService, messageSender: MessageSender) {
self.accountManager = accountManager
self.callService = callService
self.messageSender = messageSender

View file

@ -1,24 +1,24 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
import SignalServiceKit
import SignalMessaging
class ExperienceUpgrade: TSYapDatabaseObject {
@objc public class ExperienceUpgrade: TSYapDatabaseObject {
let title: String
let body: String
let image: UIImage?
required init(uniqueId: String, title: String, body: String, image: UIImage) {
@objc public required init(uniqueId: String, title: String, body: String, image: UIImage) {
self.title = title
self.body = body
self.image = image
super.init(uniqueId: uniqueId)
}
override required init(uniqueId: String?) {
@objc public override required init(uniqueId: String?) {
// This is the unfortunate seam between strict swift and fast-and-loose objc
// we can't leave these properties nil, since we really "don't know" that the superclass
// will assign them.
@ -28,7 +28,7 @@ class ExperienceUpgrade: TSYapDatabaseObject {
super.init(uniqueId: uniqueId)
}
required init!(coder: NSCoder) {
@objc public required init!(coder: NSCoder) {
// This is the unfortunate seam between strict swift and fast-and-loose objc
// we can't leave these properties nil, since we really "don't know" that the superclass
// will assign them.
@ -38,7 +38,7 @@ class ExperienceUpgrade: TSYapDatabaseObject {
super.init(coder: coder)
}
required init(dictionary dictionaryValue: [AnyHashable : Any]!) throws {
@objc public required init(dictionary dictionaryValue: [AnyHashable: Any]!) throws {
// This is the unfortunate seam between strict swift and fast-and-loose objc
// we can't leave these properties nil, since we really "don't know" that the superclass
// will assign them.
@ -48,7 +48,7 @@ class ExperienceUpgrade: TSYapDatabaseObject {
try super.init(dictionary: dictionaryValue)
}
override class func storageBehaviorForProperty(withKey propertyKey: String) -> MTLPropertyStorage {
@objc public override class func storageBehaviorForProperty(withKey propertyKey: String) -> MTLPropertyStorage {
// These exist in a hardcoded set - no need to save them, plus it allows us to
// update copy/image down the line if there was a typo and we want to re-expose
// these models in a "change log" archive.

View file

@ -13,7 +13,7 @@ enum ExperienceUpgradeId: String {
introducingCustomNotificationAudio = "005"
}
class ExperienceUpgradeFinder: NSObject {
@objc public class ExperienceUpgradeFinder: NSObject {
// MARK - Singleton class
@ -44,25 +44,26 @@ class ExperienceUpgradeFinder: NSObject {
return ExperienceUpgrade(uniqueId: ExperienceUpgradeId.introducingProfiles.rawValue,
title: NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_PROFILES_TITLE", comment: "Header for upgrade experience"),
body: NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_PROFILES_DESCRIPTION", comment: "Description of new profile feature for upgrading (existing) users"),
image:#imageLiteral(resourceName: "introductory_splash_profile"))
image: #imageLiteral(resourceName: "introductory_splash_profile"))
}
var introducingReadReceipts: ExperienceUpgrade {
return ExperienceUpgrade(uniqueId: ExperienceUpgradeId.introducingReadReceipts.rawValue,
title: NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_READ_RECEIPTS_TITLE", comment: "Header for upgrade experience"),
body: NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_READ_RECEIPTS_DESCRIPTION", comment: "Description of new profile feature for upgrading (existing) users"),
image:#imageLiteral(resourceName: "introductory_splash_read_receipts"))
image: #imageLiteral(resourceName: "introductory_splash_read_receipts"))
}
var configurableNotificationAudio: ExperienceUpgrade {
return ExperienceUpgrade(uniqueId: ExperienceUpgradeId.introducingCustomNotificationAudio.rawValue,
title: NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_NOTIFICATION_AUDIO_TITLE", comment: "Header for upgrade experience"),
body: NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_NOTIFICATION_AUDIO_DESCRIPTION", comment: "Description for notification audio customization"),
image:#imageLiteral(resourceName: "introductory_splash_custom_audio"))
image: #imageLiteral(resourceName: "introductory_splash_custom_audio"))
}
// Keep these ordered by increasing uniqueId.
private var allExperienceUpgrades: [ExperienceUpgrade] {
@objc
public var allExperienceUpgrades: [ExperienceUpgrade] {
return [
// Disable old experience upgrades. Most people have seen them by now, and accomodating multiple makes layout harder.
// Note if we ever want to show multiple experience upgrades again
@ -78,11 +79,11 @@ class ExperienceUpgradeFinder: NSObject {
// MARK: - Instance Methods
public func allUnseen(transaction: YapDatabaseReadTransaction) -> [ExperienceUpgrade] {
@objc public func allUnseen(transaction: YapDatabaseReadTransaction) -> [ExperienceUpgrade] {
return allExperienceUpgrades.filter { ExperienceUpgrade.fetch(uniqueId: $0.uniqueId!, transaction: transaction) == nil }
}
public func markAllAsSeen(transaction: YapDatabaseReadWriteTransaction) {
@objc public func markAllAsSeen(transaction: YapDatabaseReadWriteTransaction) {
Logger.info("\(logTag) marking experience upgrades as seen")
allExperienceUpgrades.forEach { $0.save(with: transaction) }
}

View file

@ -105,13 +105,13 @@ public enum PushRegistrationError: Error {
// MARK: PKPushRegistryDelegate - voIP Push Token
public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {
public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
Logger.info("\(self.logTag) in \(#function)")
assert(type == .voIP)
self.pushManager.application(UIApplication.shared, didReceiveRemoteNotification: payload.dictionaryPayload)
}
public func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, forType type: PKPushType) {
public func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
Logger.info("\(self.logTag) in \(#function)")
assert(type == .voIP)
assert(credentials.type == .voIP)
@ -123,7 +123,7 @@ public enum PushRegistrationError: Error {
fulfillVoipTokenPromise(credentials.token)
}
public func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenForType type: PKPushType) {
public func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
// It's not clear when this would happen. We've never previously handled it, but we should at
// least start learning if it happens.
owsFail("\(self.logTag) in \(#function)")
@ -145,7 +145,9 @@ public enum PushRegistrationError: Error {
let (promise, fulfill, _) = Promise<Void>.pending()
self.userNotificationSettingsPromise = promise
self.fulfillUserNotificationSettingsPromise = fulfill
self.fulfillUserNotificationSettingsPromise = {
fulfill(())
}
Logger.info("\(self.logTag) registering user notification settings")
@ -266,7 +268,7 @@ public enum PushRegistrationError: Error {
// If we've already completed registering for a voip token, resolve it immediately,
// rather than waiting for the delegate method to be called.
if let voipTokenData = voipRegistry.pushToken(forType: .voIP) {
if let voipTokenData = voipRegistry.pushToken(for: .voIP) {
Logger.info("\(self.logTag) using pre-registered voIP token")
fulfill(voipTokenData)
}

View file

@ -58,6 +58,10 @@ NSString *const OWSPrimaryStorageAppUpgradeNagDate = @"TSStorageManagerAppUpgrad
- (void)showAppUpgradeNagIfNecessary
{
if (CurrentAppContext().isRunningTests) {
return;
}
// Only show nag if we are "at rest" in the home view or registration view without any
// alerts or dialogs showing.
UIViewController *frontmostViewController =

View file

@ -80,7 +80,7 @@ import CloudKit
// backups can reuse the same record.
@objc
public class func savePersistentFileOnceToCloud(fileId: String,
fileUrlBlock: @escaping (()) -> URL?,
fileUrlBlock: @escaping () -> URL?,
success: @escaping (String) -> Void,
failure: @escaping (Error) -> Void) {
saveFileOnceToCloud(recordName: recordNameForPersistentFile(fileId: fileId),
@ -208,7 +208,7 @@ import CloudKit
@objc
public class func saveFileOnceToCloud(recordName: String,
recordType: String,
fileUrlBlock: @escaping (()) -> URL?,
fileUrlBlock: @escaping () -> URL?,
success: @escaping (String) -> Void,
failure: @escaping (Error) -> Void) {
@ -242,7 +242,7 @@ import CloudKit
@objc
public class func deleteRecordsFromCloud(recordNames: [String],
success: @escaping (()) -> Void,
success: @escaping () -> Void,
failure: @escaping (Error) -> Void) {
deleteRecordsFromCloud(recordNames: recordNames,
remainingRetries: maxRetries,
@ -252,7 +252,7 @@ import CloudKit
private class func deleteRecordsFromCloud(recordNames: [String],
remainingRetries: Int,
success: @escaping (()) -> Void,
success: @escaping () -> Void,
failure: @escaping (Error) -> Void) {
let recordIDs = recordNames.map { CKRecordID(recordName: $0) }
@ -466,7 +466,7 @@ import CloudKit
@objc
public class func downloadFileFromCloud(recordName: String,
toFileUrl: URL,
success: @escaping (()) -> Void,
success: @escaping () -> Void,
failure: @escaping (Error) -> Void) {
downloadFromCloud(recordName: recordName,

View file

@ -1,15 +1,15 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
import UIKit
@objc class TextFieldHelper: NSObject {
@objc public class TextFieldHelper: NSObject {
// Used to implement the UITextFieldDelegate method: `textField:shouldChangeCharactersInRange:replacementString`
// Takes advantage of Swift's superior unicode handling to append partial pasted text without splitting multi-byte characters.
class func textField(_ textField: UITextField, shouldChangeCharactersInRange editingRange: NSRange, replacementString: String, byteLimit: UInt) -> Bool {
@objc public class func textField(_ textField: UITextField, shouldChangeCharactersInRange editingRange: NSRange, replacementString: String, byteLimit: UInt) -> Bool {
let byteLength = { (string: String) -> UInt in
return UInt(string.utf8.count)
@ -38,7 +38,7 @@ import UIKit
var acceptableSubstring = ""
for (_, char) in replacementString.characters.enumerated() {
for (_, char) in replacementString.enumerated() {
var maybeAcceptableSubstring = acceptableSubstring
maybeAcceptableSubstring.append(char)
if (byteLength(maybeAcceptableSubstring) <= availableSpace) {
@ -48,7 +48,7 @@ import UIKit
}
}
textField.text = (existingString as NSString).replacingCharacters(in: editingRange, with:acceptableSubstring)
textField.text = (existingString as NSString).replacingCharacters(in: editingRange, with: acceptableSubstring)
// We've already handled any valid editing manually, so prevent further changes.
return false

View file

@ -24,6 +24,7 @@ class AttachmentPointerView: UIView {
}
}
@objc
required init(attachmentPointer: TSAttachmentPointer, isIncoming: Bool) {
self.isIncoming = isIncoming
self.attachmentPointer = attachmentPointer
@ -52,7 +53,7 @@ class AttachmentPointerView: UIView {
NotificationCenter.default.removeObserver(self)
}
internal func attachmentDownloadProgress(_ notification: Notification) {
@objc internal func attachmentDownloadProgress(_ notification: Notification) {
guard let attachmentId = attachmentPointer.uniqueId else {
owsFail("Missing attachment id.")
return

View file

@ -5,9 +5,9 @@
import UIKit
import SignalServiceKit
@objc class AudioProgressView: UIView {
@objc public class AudioProgressView: UIView {
override var bounds: CGRect {
@objc public override var bounds: CGRect {
didSet {
if oldValue != bounds {
updateSubviews()
@ -15,7 +15,7 @@ import SignalServiceKit
}
}
override var frame: CGRect {
@objc public override var frame: CGRect {
didSet {
if oldValue != frame {
updateSubviews()
@ -23,13 +23,13 @@ import SignalServiceKit
}
}
var horizontalBarColor = UIColor.black {
@objc public var horizontalBarColor = UIColor.black {
didSet {
updateContent()
}
}
var progressColor = UIColor.blue {
@objc public var progressColor = UIColor.blue {
didSet {
updateContent()
}
@ -38,7 +38,7 @@ import SignalServiceKit
private let horizontalBarLayer: CAShapeLayer
private let progressLayer: CAShapeLayer
var progress: CGFloat = 0 {
@objc public var progress: CGFloat = 0 {
didSet {
if oldValue != progress {
updateContent()
@ -47,7 +47,7 @@ import SignalServiceKit
}
@available(*, unavailable, message:"use other constructor instead.")
required init?(coder aDecoder: NSCoder) {
@objc public required init?(coder aDecoder: NSCoder) {
fatalError("\(#function) is unimplemented.")
}

View file

@ -65,7 +65,7 @@ class ContactCell: UITableViewCell {
}
}
func didChangePreferredContentSize() {
@objc func didChangePreferredContentSize() {
self.titleLabel.font = UIFont.ows_dynamicTypeBody
self.subtitleLabel.font = UIFont.ows_dynamicTypeSubheadline
}
@ -130,13 +130,13 @@ fileprivate extension CNContact {
let boldDescriptor = font.fontDescriptor.withSymbolicTraits(.traitBold)
let boldAttributes = [
NSFontAttributeName: UIFont(descriptor: boldDescriptor!, size: 0)
NSAttributedStringKey.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[CNContactPropertyAttribute] as? String, property == keyToHighlight {
if let property = attrs[NSAttributedStringKey(rawValue: CNContactPropertyAttribute)] as? String, property == keyToHighlight {
highlightedName.addAttributes(boldAttributes, range: range)
}
})

View file

@ -14,7 +14,7 @@ class PanDirectionGestureRecognizer: UIPanGestureRecognizer {
let direction: PanDirection
init(direction: PanDirection, target: AnyObject, action: Selector) {
@objc init(direction: PanDirection, target: AnyObject, action: Selector) {
self.direction = direction
super.init(target: target, action: action)

View file

@ -51,6 +51,7 @@ import SignalServiceKit
fatalError("init(coder:) has not been implemented")
}
@objc
public func configure(thread: TSGroupThread, contactsManager: OWSContactsManager) {
if let groupName = thread.groupModel.groupName, !groupName.isEmpty {
self.nameLabel.text = groupName

View file

@ -11,16 +11,19 @@ protocol QuotedReplyPreviewDelegate: class {
@objc
class QuotedReplyPreview: UIView {
@objc
public weak var delegate: QuotedReplyPreviewDelegate?
private let quotedReply: OWSQuotedReplyModel
private var quotedMessageView: OWSQuotedMessageView?
private var heightConstraint: NSLayoutConstraint!
@objc
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc
init(quotedReply: OWSQuotedReplyModel) {
self.quotedReply = quotedReply
@ -83,7 +86,7 @@ class QuotedReplyPreview: UIView {
self.heightConstraint.constant = size.height
}
func contentSizeCategoryDidChange(_ notification: Notification) {
@objc func contentSizeCategoryDidChange(_ notification: Notification) {
Logger.debug("\(self.logTag) in \(#function)")
updateContents()

View file

@ -125,7 +125,7 @@ class ReminderView: UIView {
iconView.autoSetDimension(.width, toSize: 13)
}
func handleTap(gestureRecognizer: UIGestureRecognizer) {
@objc func handleTap(gestureRecognizer: UIGestureRecognizer) {
tapAction()
}
}

View file

@ -18,7 +18,13 @@ enum PushNotificationRequestResult: String {
}
class FailingTSAccountManager: TSAccountManager {
let phoneNumberAwaitingVerification = "+13235555555"
override public init(networkManager: TSNetworkManager, primaryStorage: OWSPrimaryStorage) {
SwiftAssertIsOnMainThread(#function)
super.init(networkManager: networkManager, primaryStorage: primaryStorage)
self.phoneNumberAwaitingVerification = "+13235555555"
}
override func verifyAccount(withCode: String,
pin: String?,

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import XCTest
@ -12,35 +12,37 @@ import WebRTC
class FakePeerConnectionClientDelegate: PeerConnectionClientDelegate {
enum ConnectionState {
case connected, failed
case connected, disconnected, failed
}
var connectionState: ConnectionState?
var localIceCandidates = [RTCIceCandidate]()
var dataChannelMessages = [OWSWebRTCProtosData]()
internal func peerConnectionClientIceConnected(_ peerconnectionClient: PeerConnectionClient) {
func peerConnectionClientIceConnected(_ peerconnectionClient: PeerConnectionClient) {
connectionState = .connected
}
internal func peerConnectionClientIceFailed(_ peerconnectionClient: PeerConnectionClient) {
func peerConnectionClientIceDisconnected(_ peerconnectionClient: PeerConnectionClient) {
connectionState = .disconnected
}
func peerConnectionClientIceFailed(_ peerconnectionClient: PeerConnectionClient) {
connectionState = .failed
}
internal func peerConnectionClient(_ peerconnectionClient: PeerConnectionClient, addedLocalIceCandidate iceCandidate: RTCIceCandidate) {
func peerConnectionClient(_ peerconnectionClient: PeerConnectionClient, addedLocalIceCandidate iceCandidate: RTCIceCandidate) {
localIceCandidates.append(iceCandidate)
}
internal func peerConnectionClient(_ peerconnectionClient: PeerConnectionClient, received dataChannelMessage: OWSWebRTCProtosData) {
func peerConnectionClient(_ peerconnectionClient: PeerConnectionClient, received dataChannelMessage: OWSWebRTCProtosData) {
dataChannelMessages.append(dataChannelMessage)
}
internal func peerConnectionClient(_ peerconnectionClient: PeerConnectionClient, didUpdateLocal videoTrack: RTCVideoTrack?) {
func peerConnectionClient(_ peerconnectionClient: PeerConnectionClient, didUpdateLocal videoTrack: RTCVideoTrack?) {
}
internal func peerConnectionClient(_ peerconnectionClient: PeerConnectionClient, didUpdateRemote videoTrack: RTCVideoTrack?) {
func peerConnectionClient(_ peerconnectionClient: PeerConnectionClient, didUpdateRemote videoTrack: RTCVideoTrack?) {
}
}

View file

@ -32,10 +32,10 @@ final class ContactsPickerTest: XCTestCase {
let emailOnlyContactD = CNMutableContact()
emailOnlyContactD.emailAddresses.append(CNLabeledValue(label: nil, value: "dude@bla.com"))
let contactsPicker = ContactsPicker(delegate: nil)
let contactsPicker = ContactsPicker(allowsMultipleSelection: false, subtitleCellType: .phoneNumber)
let collatedContacts = contactsPicker.collatedContacts([emailOnlyContactB, emailOnlyContactD])
let sectionTitles = contactsPicker.collation.sectionTitles
let sectionTitles = contactsPicker.collationForTests.sectionTitles
if let bIndex = sectionTitles.index(of: "B") {
let bSectionContacts = collatedContacts[bIndex]
XCTAssertEqual(bSectionContacts.first, emailOnlyContactB)
@ -54,10 +54,10 @@ final class ContactsPickerTest: XCTestCase {
nameAndEmailContact.givenName = "Alice"
nameAndEmailContact.emailAddresses.append(CNLabeledValue(label: nil, value: "nameAndEmail@bla.com"))
let contactsPicker = ContactsPicker(delegate: nil)
let contactsPicker = ContactsPicker(allowsMultipleSelection: false, subtitleCellType: .phoneNumber)
let collatedContacts = contactsPicker.collatedContacts([nameAndEmailContact])
let sectionTitles = contactsPicker.collation.sectionTitles
let sectionTitles = contactsPicker.collationForTests.sectionTitles
if let aIndex = sectionTitles.index(of: "A") {
let aSectionContacts = collatedContacts[aIndex]
XCTAssertEqual(aSectionContacts.first, nameAndEmailContact)

View file

@ -27,6 +27,7 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[];
#import <SignalMessaging/OWSContactsSyncing.h>
#import <SignalMessaging/OWSDatabaseMigration.h>
#import <SignalMessaging/OWSFormat.h>
#import <SignalMessaging/OWSGroupAvatarBuilder.h>
#import <SignalMessaging/OWSLogger.h>
#import <SignalMessaging/OWSMath.h>
#import <SignalMessaging/OWSNavigationController.h>
@ -37,10 +38,12 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[];
#import <SignalMessaging/OWSUserProfile.h>
#import <SignalMessaging/OWSWindowManager.h>
#import <SignalMessaging/Release.h>
#import <SignalMessaging/ScreenLockViewController.h>
#import <SignalMessaging/SharingThreadPickerViewController.h>
#import <SignalMessaging/SignalKeyingStorage.h>
#import <SignalMessaging/TSUnreadIndicatorInteraction.h>
#import <SignalMessaging/ThreadUtil.h>
#import <SignalMessaging/ThreadViewHelper.h>
#import <SignalMessaging/UIColor+OWS.h>
#import <SignalMessaging/UIFont+OWS.h>
#import <SignalMessaging/UIUtil.h>

View file

@ -12,10 +12,12 @@ public protocol ReturnToCallViewControllerDelegate: class {
@objc
public class ReturnToCallViewController: UIViewController {
@objc
public weak var delegate: ReturnToCallViewControllerDelegate?
let returnToCallLabel = UILabel()
@objc
public func startAnimating() {
NotificationCenter.default.addObserver(self, selector: #selector(didTapStatusBar(notification:)), name: .TappedStatusBar, object: nil)
self.returnToCallLabel.layer.removeAllAnimations()
@ -27,6 +29,7 @@ public class ReturnToCallViewController: UIViewController {
completion: { _ in self.returnToCallLabel.alpha = 1 })
}
@objc
public func stopAnimating() {
NotificationCenter.default.removeObserver(self, name: .TappedStatusBar, object: nil)
self.returnToCallLabel.layer.removeAllAnimations()

View file

@ -7,16 +7,20 @@ import Foundation
@objc
public class ContactShareViewModel: NSObject {
@objc
public let dbRecord: OWSContact
@objc
public var avatarImageData: Data? {
didSet {
self.cachedAvatarImage = nil
}
}
var cachedAvatarImage: UIImage?
var avatarImage: UIImage? {
private var cachedAvatarImage: UIImage?
@objc
public var avatarImage: UIImage? {
if self.cachedAvatarImage != nil {
return self.cachedAvatarImage
}
@ -29,11 +33,13 @@ public class ContactShareViewModel: NSObject {
return cachedAvatarImage
}
@objc
public required init(contactShareRecord: OWSContact, avatarImageData: Data?) {
self.dbRecord = contactShareRecord
self.avatarImageData = avatarImageData
}
@objc
public convenience init(contactShareRecord: OWSContact, transaction: YapDatabaseReadTransaction) {
if let avatarAttachment = contactShareRecord.avatarAttachment(with: transaction) as? TSAttachmentStream {
self.init(contactShareRecord: contactShareRecord, avatarImageData: avatarAttachment.validStillImageData())
@ -42,6 +48,7 @@ public class ContactShareViewModel: NSObject {
}
}
@objc
public func getAvatarImage(diameter: CGFloat, contactsManager: OWSContactsManager) -> UIImage {
if let avatarImage = avatarImage {
return avatarImage
@ -71,6 +78,7 @@ public class ContactShareViewModel: NSObject {
// MARK: Delegated -> dbRecord
@objc
public var name: OWSContactName {
get {
return dbRecord.name
@ -80,6 +88,7 @@ public class ContactShareViewModel: NSObject {
}
}
@objc
public var addresses: [OWSContactAddress] {
get {
return dbRecord.addresses
@ -89,6 +98,7 @@ public class ContactShareViewModel: NSObject {
}
}
@objc
public var emails: [OWSContactEmail] {
get {
return dbRecord.emails
@ -98,6 +108,7 @@ public class ContactShareViewModel: NSObject {
}
}
@objc
public var phoneNumbers: [OWSContactPhoneNumber] {
get {
return dbRecord.phoneNumbers
@ -107,30 +118,37 @@ public class ContactShareViewModel: NSObject {
}
}
@objc
public func systemContactsWithSignalAccountPhoneNumbers(_ contactsManager: ContactsManagerProtocol) -> [String] {
return dbRecord.systemContactsWithSignalAccountPhoneNumbers(contactsManager)
}
@objc
public func systemContactPhoneNumbers(_ contactsManager: ContactsManagerProtocol) -> [String] {
return dbRecord.systemContactPhoneNumbers(contactsManager)
}
@objc
public func e164PhoneNumbers() -> [String] {
return dbRecord.e164PhoneNumbers()
}
@objc
public var displayName: String {
return dbRecord.name.displayName
}
@objc
public var ows_isValid: Bool {
return dbRecord.ows_isValid()
}
@objc
public var isProfileAvatar: Bool {
return dbRecord.isProfileAvatar
}
@objc
public func cnContact(mergedWithExistingContact existingContact: Contact) -> CNContact? {
guard let newCNContact = OWSContacts.systemContact(for: self.dbRecord, imageData: self.avatarImageData) else {
@ -141,6 +159,7 @@ public class ContactShareViewModel: NSObject {
return existingContact.buildCNContact(mergedWithNewContact: newCNContact)
}
@objc
public func copy(withName name: OWSContactName) -> ContactShareViewModel {
// TODO move the `copy` logic into the view model?
@ -149,6 +168,7 @@ public class ContactShareViewModel: NSObject {
return ContactShareViewModel(contactShareRecord: newDbRecord, avatarImageData: self.avatarImageData)
}
@objc
public func newContact(withName name: OWSContactName) -> ContactShareViewModel {
// TODO move the `newContact` logic into the view model?

View file

@ -95,7 +95,7 @@ public class ConversationAvatarImageView: AvatarImageView {
fatalError("init(coder:) has not been implemented")
}
func handleSignalAccountsChanged(notification: Notification) {
@objc func handleSignalAccountsChanged(notification: Notification) {
Logger.debug("\(self.logTag) in \(#function)")
// PERF: It would be nice if we could do this only if *this* user's SignalAccount changed,
@ -104,7 +104,7 @@ public class ConversationAvatarImageView: AvatarImageView {
self.updateImage()
}
func handleOtherUsersProfileChanged(notification: Notification) {
@objc func handleOtherUsersProfileChanged(notification: Notification) {
Logger.debug("\(self.logTag) in \(#function)")
guard let changedRecipientId = notification.userInfo?[kNSNotificationKey_ProfileRecipientId] as? String else {
@ -126,7 +126,7 @@ public class ConversationAvatarImageView: AvatarImageView {
self.updateImage()
}
func handleGroupAvatarChanged(notification: Notification) {
@objc func handleGroupAvatarChanged(notification: Notification) {
Logger.debug("\(self.logTag) in \(#function)")
guard let changedGroupThreadId = notification.userInfo?[TSGroupThread_NotificationKey_UniqueId] as? String else {

View file

@ -16,6 +16,7 @@ public protocol DisappearingTimerConfigurationViewDelegate: class {
@objc
public class DisappearingTimerConfigurationView: UIView {
@objc
public weak var delegate: DisappearingTimerConfigurationViewDelegate? {
didSet {
// gesture recognizer is only enabled when a delegate is assigned.

View file

@ -6,30 +6,35 @@ import Foundation
import UIKit
@objc
protocol NavBarLayoutDelegate: class {
public protocol NavBarLayoutDelegate: class {
func navBarCallLayoutDidChange(navbar: OWSNavigationBar)
}
@objc
class OWSNavigationBar: UINavigationBar {
public class OWSNavigationBar: UINavigationBar {
weak var navBarLayoutDelegate: NavBarLayoutDelegate?
@objc
public weak var navBarLayoutDelegate: NavBarLayoutDelegate?
let navbarWithoutStatusHeight: CGFloat = 44
@objc
public let navbarWithoutStatusHeight: CGFloat = 44
var callBannerHeight: CGFloat {
@objc
public var callBannerHeight: CGFloat {
return OWSWindowManagerCallScreenHeight()
}
var statusBarHeight: CGFloat {
@objc
public var statusBarHeight: CGFloat {
return CurrentAppContext().statusBarHeight
}
var fullWidth: CGFloat {
@objc
public var fullWidth: CGFloat {
return UIScreen.main.bounds.size.width
}
required init?(coder aDecoder: NSCoder) {
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@ -54,7 +59,7 @@ class OWSNavigationBar: UINavigationBar {
self.navBarLayoutDelegate?.navBarCallLayoutDidChange(navbar: self)
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
public override func sizeThatFits(_ size: CGSize) -> CGSize {
guard OWSWindowManager.shared().hasCall() else {
return super.sizeThatFits(size)
}
@ -69,7 +74,7 @@ class OWSNavigationBar: UINavigationBar {
}
}
override func layoutSubviews() {
public override func layoutSubviews() {
guard OWSWindowManager.shared().hasCall() else {
super.layoutSubviews()
return

View file

@ -23,7 +23,7 @@ public class TappableStackView: UIStackView {
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(wasTapped)))
}
func wasTapped(sender: UIGestureRecognizer) {
@objc func wasTapped(sender: UIGestureRecognizer) {
Logger.info("\(logTag) \(#function)")
guard sender.state == .recognized else {

View file

@ -22,7 +22,7 @@ public class TappableView: UIView {
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(wasTapped)))
}
func wasTapped(sender: UIGestureRecognizer) {
@objc func wasTapped(sender: UIGestureRecognizer) {
Logger.info("\(logTag) \(#function)")
guard sender.state == .recognized else {

View file

@ -216,7 +216,7 @@ public class AttachmentApprovalViewController: OWSViewController, CaptioningTool
}
}
public func didTapPlayerView(_ gestureRecognizer: UIGestureRecognizer) {
@objc public func didTapPlayerView(_ gestureRecognizer: UIGestureRecognizer) {
assert(self.videoPlayer != nil)
self.pauseVideo()
}
@ -251,7 +251,7 @@ public class AttachmentApprovalViewController: OWSViewController, CaptioningTool
self.playVideo()
}
func cancelPressed(sender: UIButton) {
@objc func cancelPressed(sender: UIButton) {
self.delegate?.attachmentApproval(self, didCancelAttachment: attachment)
}
@ -619,7 +619,7 @@ class CaptioningToolbar: UIView, UITextViewDelegate {
bottomGradient.autoPinEdgesToSuperviewEdges(with: .zero, excludingEdge: .top)
}
func didTapSend() {
@objc func didTapSend() {
self.captioningToolbarDelegate?.captioningToolbarDidTapSend(self, captionText: self.textView.text)
}

View file

@ -203,7 +203,7 @@ class ContactShareFieldView: UIStackView {
self.addArrangedSubview(previewView)
}
func wasTapped(sender: UIGestureRecognizer) {
@objc func wasTapped(sender: UIGestureRecognizer) {
Logger.info("\(self.logTag) \(#function)")
guard sender.state == .recognized else {
@ -401,7 +401,7 @@ public class ContactShareApprovalViewController: OWSViewController, EditContactS
func createNameRow() -> UIView {
let nameVMargin = CGFloat(16)
let stackView = TappableStackView(actionBlock: { [weak self] _ in
let stackView = TappableStackView(actionBlock: { [weak self] in
guard let strongSelf = self else { return }
strongSelf.didPressEditName()
})
@ -447,7 +447,7 @@ public class ContactShareApprovalViewController: OWSViewController, EditContactS
// MARK: -
func didPressSendButton() {
@objc func didPressSendButton() {
SwiftAssertIsOnMainThread(#function)
guard isAtLeastOneFieldSelected() else {
@ -475,7 +475,7 @@ public class ContactShareApprovalViewController: OWSViewController, EditContactS
delegate.approveContactShare(self, didApproveContactShare: filteredContactShare)
}
func didPressCancel() {
@objc func didPressCancel() {
Logger.info("\(logTag) \(#function)")
guard let delegate = self.delegate else {

View file

@ -76,7 +76,7 @@ class ContactNameFieldView: UIView {
valueView.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
}
func wasTapped(sender: UIGestureRecognizer) {
@objc func wasTapped(sender: UIGestureRecognizer) {
Logger.info("\(self.logTag) \(#function)")
guard sender.state == .recognized else {
@ -86,7 +86,7 @@ class ContactNameFieldView: UIView {
valueView.becomeFirstResponder()
}
func textFieldDidChange(sender: UITextField) {
@objc func textFieldDidChange(sender: UITextField) {
Logger.info("\(self.logTag) \(#function)")
hasUnsavedChanges = true
@ -285,7 +285,7 @@ public class EditContactShareNameViewController: OWSViewController, ContactNameF
// MARK: -
func didPressSave() {
@objc func didPressSave() {
Logger.info("\(logTag) \(#function)")
guard let newName = OWSContactName() else {
@ -315,7 +315,7 @@ public class EditContactShareNameViewController: OWSViewController, ContactNameF
navigationController.popViewController(animated: true)
}
func didPressCancel() {
@objc func didPressCancel() {
Logger.info("\(logTag) \(#function)")
guard let navigationController = self.navigationController else {

View file

@ -164,7 +164,7 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
// it's superview is big enough to contain it.
stackView.autoPinWidthToSuperview()
stackView.autoVCenterInSuperview()
NSLayoutConstraint.autoSetPriority(UILayoutPriorityDefaultLow) {
NSLayoutConstraint.autoSetPriority(UILayoutPriority.defaultLow) {
stackView.autoPinHeightToSuperview()
}
stackView.autoPinEdge(toSuperviewEdge: .top, withInset: 0, relation: .greaterThanOrEqual)
@ -277,7 +277,7 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
// it's superview is big enough to contain it.
stackView.autoPinWidthToSuperview()
stackView.autoVCenterInSuperview()
NSLayoutConstraint.autoSetPriority(UILayoutPriorityDefaultLow) {
NSLayoutConstraint.autoSetPriority(UILayoutPriority.defaultLow) {
stackView.autoPinHeightToSuperview()
}
stackView.autoPinEdge(toSuperviewEdge: .top, withInset: 0, relation: .greaterThanOrEqual)

View file

@ -200,11 +200,11 @@ public class MessageApprovalViewController: OWSViewController, UITextViewDelegat
// MARK: - Event Handlers
func cancelPressed(sender: UIButton) {
@objc func cancelPressed(sender: UIButton) {
delegate?.messageApprovalDidCancel(self)
}
func sendPressed(sender: UIButton) {
@objc func sendPressed(sender: UIButton) {
delegate?.messageApproval(self, didApproveMessage: self.textView.text)
}

View file

@ -13,12 +13,14 @@ protocol OWSVideoPlayerDelegate: class {
@objc
public class OWSVideoPlayer: NSObject {
@objc
let avPlayer: AVPlayer
let audioActivity: AudioActivity
@objc
weak var delegate: OWSVideoPlayerDelegate?
init(url: URL) {
@objc init(url: URL) {
self.avPlayer = AVPlayer(url: url)
self.audioActivity = AudioActivity(audioDescription: "[OWSVideoPlayer] url:\(url)")
@ -32,11 +34,13 @@ public class OWSVideoPlayer: NSObject {
// MARK: Playback Controls
@objc
public func pause() {
avPlayer.pause()
OWSAudioSession.shared.endAudioActivity(self.audioActivity)
}
@objc
public func play() {
OWSAudioSession.shared.startPlaybackAudioActivity(self.audioActivity)
@ -53,6 +57,7 @@ public class OWSVideoPlayer: NSObject {
avPlayer.play()
}
@objc
public func stop() {
avPlayer.pause()
avPlayer.seek(to: kCMTimeZero)

View file

@ -958,7 +958,7 @@ public class SignalAttachment: NSObject {
}
exportSession.shouldOptimizeForNetworkUse = true
exportSession.outputFileType = AVFileTypeMPEG4
exportSession.outputFileType = AVFileType.mp4
exportSession.metadataItemFilter = AVMetadataItemFilter.forSharing()
let exportURL = videoTempPath.appendingPathComponent(UUID().uuidString).appendingPathExtension("mp4")
@ -1011,6 +1011,7 @@ public class SignalAttachment: NSObject {
return VideoCompressionResult(attachmentPromise: attachmentPromise, exportSession: exportSession)
}
@objc
public class func isInvalidVideo(dataSource: DataSource, dataUTI: String) -> Bool {
guard videoUTISet.contains(dataUTI) else {
// not a video

View file

@ -7,6 +7,7 @@ import AVFoundation
@objc
public class VideoPlayerView: UIView {
@objc
var player: AVPlayer? {
get {
return playerLayer.player
@ -75,6 +76,7 @@ public class PlayerProgressBar: UIView {
private let kPreferredTimeScale: CMTimeScale = 100
@objc
public var player: AVPlayer? {
didSet {
guard let item = player?.currentItem else {
@ -112,7 +114,7 @@ public class PlayerProgressBar: UIView {
// Configure controls
let kLabelFont = UIFont.monospacedDigitSystemFont(ofSize: 12, weight: UIFontWeightRegular)
let kLabelFont = UIFont.monospacedDigitSystemFont(ofSize: 12, weight: UIFont.Weight.regular)
positionLabel.font = kLabelFont
remainingLabel.font = kLabelFont

View file

@ -1,19 +1,22 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import PromiseKit
@objc
public extension AnyPromise {
/**
* Sometimes there isn't a straight forward candidate to retain a promise, in that case we tell the
* promise to self retain, until it completes to avoid the risk it's GC'd before completion.
*/
@objc
func retainUntilComplete() {
// Unfortunately, there is (currently) no way to surpress the
// compiler warning: "Variable 'retainCycle' was written to, but never read"
var retainCycle: AnyPromise? = self
self.always {
assert(retainCycle != nil)
retainCycle = nil
}
}
@ -29,6 +32,7 @@ public extension Promise {
// compiler warning: "Variable 'retainCycle' was written to, but never read"
var retainCycle: Promise<T>? = self
self.always {
assert(retainCycle != nil)
retainCycle = nil
}
}

View file

@ -4,12 +4,14 @@
import Foundation
@objc
public extension UIDevice {
var supportsCallKit: Bool {
return ProcessInfo().isOperatingSystemAtLeast(OperatingSystemVersion(majorVersion: 10, minorVersion: 0, patchVersion: 0))
}
var isIPhoneX: Bool {
@objc
public var isIPhoneX: Bool {
switch UIScreen.main.nativeBounds.height {
case 1136:
// iPhone 5 or 5S or 5C

View file

@ -15,6 +15,7 @@ public class ModalActivityIndicatorViewController: OWSViewController {
let canCancel: Bool
@objc
public var wasCancelled: Bool = false
var activityIndicator: UIActivityIndicatorView?
@ -35,6 +36,7 @@ public class ModalActivityIndicatorViewController: OWSViewController {
super.init(nibName: nil, bundle: nil)
}
@objc
public class func present(fromViewController: UIViewController,
canCancel: Bool, backgroundBlock : @escaping (ModalActivityIndicatorViewController) -> Void) {
SwiftAssertIsOnMainThread(#function)
@ -50,6 +52,7 @@ public class ModalActivityIndicatorViewController: OWSViewController {
}
}
@objc
public func dismiss(completion : @escaping () -> Void) {
SwiftAssertIsOnMainThread(#function)
@ -132,7 +135,7 @@ public class ModalActivityIndicatorViewController: OWSViewController {
self.presentTimer = nil
}
func presentTimerFired() {
@objc func presentTimerFired() {
SwiftAssertIsOnMainThread(#function)
clearTimer()
@ -143,7 +146,7 @@ public class ModalActivityIndicatorViewController: OWSViewController {
}
}
func cancelPressed() {
@objc func cancelPressed() {
SwiftAssertIsOnMainThread(#function)
wasCancelled = true

View file

@ -13,8 +13,8 @@ public class AudioActivity: NSObject {
return "<\(self.logTag) audioDescription: \"\(audioDescription)\">"
}
public
init(audioDescription: String) {
@objc
public init(audioDescription: String) {
self.audioDescription = audioDescription
}
@ -27,7 +27,7 @@ public class AudioActivity: NSObject {
public class OWSAudioSession: NSObject {
// Force singleton access
public static let shared = OWSAudioSession()
@objc public static let shared = OWSAudioSession()
private override init() {}
private let avAudioSession = AVAudioSession.sharedInstance()
@ -35,6 +35,7 @@ public class OWSAudioSession: NSObject {
// Respects hardware mute switch, plays through external speaker, mixes with backround audio
// appropriate for foreground sound effects.
@objc
public func startAmbientAudioActivity(_ audioActivity: AudioActivity) {
Logger.debug("\(logTag) in \(#function)")
@ -56,6 +57,7 @@ public class OWSAudioSession: NSObject {
}
// Ignores hardware mute switch, plays through external speaker
@objc
public func startPlaybackAudioActivity(_ audioActivity: AudioActivity) {
Logger.debug("\(logTag) in \(#function)")
@ -71,6 +73,7 @@ public class OWSAudioSession: NSObject {
}
}
@objc
public func startRecordingAudioActivity(_ audioActivity: AudioActivity) -> Bool {
Logger.debug("\(logTag) in \(#function)")
@ -90,6 +93,7 @@ public class OWSAudioSession: NSObject {
}
}
@objc
public func startAudioActivity(_ audioActivity: AudioActivity) {
Logger.debug("\(logTag) in \(#function) with \(audioActivity)")
@ -99,6 +103,7 @@ public class OWSAudioSession: NSObject {
self.currentActivities.append(Weak(value: audioActivity))
}
@objc
public func endAudioActivity(_ audioActivity: AudioActivity) {
Logger.debug("\(logTag) in \(#function) with audioActivity: \(audioActivity)")
@ -171,6 +176,7 @@ public class OWSAudioSession: NSObject {
* This must be called before any audio tracks are added to the peerConnection, else we'll start recording before all
* our signaling is set up.
*/
@objc
public func configureRTCAudio() {
Logger.info("\(logTag) in \(#function)")
rtcAudioSession.useManualAudio = true
@ -180,6 +186,7 @@ public class OWSAudioSession: NSObject {
* Because we useManualAudio with our RTCAudioSession, we have to start/stop the recording audio session ourselves.
* See header for details on manual audio.
*/
@objc
public var isRTCAudioEnabled: Bool {
get {
return rtcAudioSession.isAudioEnabled

View file

@ -14,13 +14,14 @@ public class OWS106EnsureProfileComplete: OWSDatabaseMigration {
private static var sharedCompleteRegistrationFixerJob: CompleteRegistrationFixerJob?
// increment a similar constant for each migration.
@objc
class func migrationId() -> String {
return "106"
}
// Overriding runUp since we have some specific completion criteria which
// is more likely to fail since it involves network requests.
override public func runUp(completion:@escaping ((Void)) -> Void) {
override public func runUp(completion:@escaping () -> Void) {
let job = CompleteRegistrationFixerJob(completionHandler: { (didSucceed) in
if (didSucceed) {
@ -98,7 +99,7 @@ public class OWS106EnsureProfileComplete: OWSDatabaseMigration {
ProfileFetcherJob(networkManager: networkManager).getProfile(recipientId: localRecipientId).then { _ -> Void in
Logger.info("\(self.TAG) verified recipient profile is in good shape: \(localRecipientId)")
fulfill()
fulfill(())
}.catch { error in
switch error {
case SignalServiceProfile.ValidationError.invalidIdentityKey(let description):
@ -107,7 +108,7 @@ public class OWS106EnsureProfileComplete: OWSDatabaseMigration {
TSPreKeyManager.registerPreKeys(with: .signedAndOneTime,
success: {
Logger.info("\(self.TAG) successfully uploaded pre-keys. Profile should be fixed.")
fulfill()
fulfill(())
},
failure: { _ in
reject(OWSErrorWithCodeDescription(.signalServiceFailure, "\(self.TAG) Unknown error in \(#function)"))

View file

@ -20,6 +20,7 @@ public class DeviceSleepManager: NSObject {
let TAG = "[DeviceSleepManager]"
@objc
public static let sharedInstance = DeviceSleepManager()
private class SleepBlock: CustomDebugStringConvertible {
@ -57,6 +58,7 @@ public class DeviceSleepManager: NSObject {
ensureSleepBlocking()
}
@objc
public func addBlock(blockObject: NSObject) {
SwiftAssertIsOnMainThread(#function)
@ -65,6 +67,7 @@ public class DeviceSleepManager: NSObject {
ensureSleepBlocking()
}
@objc
public func removeBlock(blockObject: NSObject) {
SwiftAssertIsOnMainThread(#function)

View file

@ -152,20 +152,22 @@ extension String {
static let TAG = "[DisplayableText]"
public let fullText: String
public let displayText: String
public let isTextTruncated: Bool
public let jumbomojiCount: UInt
@objc public let fullText: String
@objc public let displayText: String
@objc public let isTextTruncated: Bool
@objc public let jumbomojiCount: UInt
@objc
static let kMaxJumbomojiCount: UInt = 5
// This value is a bit arbitrary since we don't need to be 100% correct about
// rendering "Jumbomoji". It allows us to place an upper bound on worst-case
// performacne.
@objc
static let kMaxCharactersPerEmojiCount: UInt = 10
// MARK: Initializers
init(fullText: String, displayText: String, isTextTruncated: Bool) {
@objc public init(fullText: String, displayText: String, isTextTruncated: Bool) {
self.fullText = fullText
self.displayText = displayText
self.isTextTruncated = isTextTruncated

View file

@ -7,14 +7,17 @@ public class AnyLRUCache: NSObject {
let backingCache: LRUCache<NSObject, NSObject>
@objc
public init(maxSize: Int) {
backingCache = LRUCache(maxSize: maxSize)
}
@objc
public func get(key: NSObject) -> NSObject? {
return self.backingCache.get(key: key)
}
@objc
public func set(key: NSObject, value: NSObject) {
self.backingCache.set(key: key, value: value)
}

View file

@ -20,26 +20,31 @@ public class OWSMessagesBubbleImageFactory: NSObject {
return UIView().isRTL()
}()
@objc
public lazy var incoming: JSQMessagesBubbleImage = {
let color = bubbleColorIncoming
let color = OWSMessagesBubbleImageFactory.bubbleColorIncoming
return self.incoming(color: color)
}()
@objc
public lazy var outgoing: JSQMessagesBubbleImage = {
let color = bubbleColorOutgoingSent
let color = OWSMessagesBubbleImageFactory.bubbleColorOutgoingSent
return self.outgoing(color: color)
}()
@objc
public lazy var currentlyOutgoing: JSQMessagesBubbleImage = {
let color = bubbleColorOutgoingSending
let color = OWSMessagesBubbleImageFactory.bubbleColorOutgoingSending
return self.outgoing(color: color)
}()
@objc
public lazy var outgoingFailed: JSQMessagesBubbleImage = {
let color = bubbleColorOutgoingUnsent
let color = OWSMessagesBubbleImageFactory.bubbleColorOutgoingUnsent
return self.outgoing(color: color)
}()
@objc
public func bubble(message: TSMessage) -> JSQMessagesBubbleImage {
if message is TSIncomingMessage {
return self.incoming
@ -70,6 +75,7 @@ public class OWSMessagesBubbleImageFactory: NSObject {
@objc
public static let bubbleColorOutgoingSent = UIColor.ows_materialBlue
@objc
public func bubbleColor(message: TSMessage) -> UIColor {
if message is TSIncomingMessage {
return OWSMessagesBubbleImageFactory.bubbleColorIncoming

View file

@ -60,6 +60,7 @@ import Foundation
}
@objc public class MediaStrings: NSObject {
@objc
static public let allMedia = NSLocalizedString("MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON", comment: "nav bar button item")
}

View file

@ -17,6 +17,11 @@ extern NSString *const kNSNotificationName_LocalNumberDidChange;
@interface TSAccountManager : NSObject
// This property is exposed for testing purposes only.
#ifdef DEBUG
@property (nonatomic, nullable) NSString *phoneNumberAwaitingVerification;
#endif
#pragma mark - Initializers
- (instancetype)init NS_UNAVAILABLE;

View file

@ -25,8 +25,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, copy) NSString *messageDraft;
@property (atomic, nullable) NSDate *mutedUntilDate;
- (TSInteraction *)lastInteractionWithTranscation:(YapDatabaseReadTransaction *)transaction;
@end
@implementation TSThread