Respond to CR.

pull/1/head
Matthew Chen 7 years ago
parent f10b549940
commit 4746948dfe

@ -18,7 +18,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
var callUIAdapter: CallUIAdapter { var callUIAdapter: CallUIAdapter {
return SignalApp.shared().callUIAdapter return SignalApp.shared().callUIAdapter
} }
let contactsManager: OWSContactsManager let contactsManager: OWSContactsManager
// MARK: Properties // MARK: Properties
@ -134,7 +134,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
self.call = call self.call = call
self.thread = TSContactThread.getOrCreateThread(contactId: call.remotePhoneNumber) self.thread = TSContactThread.getOrCreateThread(contactId: call.remotePhoneNumber)
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
allAudioSources = Set(callUIAdapter.audioService.availableInputs) allAudioSources = Set(callUIAdapter.audioService.availableInputs)
assert(callUIAdapter.audioService.delegate == nil) assert(callUIAdapter.audioService.delegate == nil)
@ -144,9 +144,9 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
func observeNotifications() { func observeNotifications() {
NotificationCenter.default.addObserver(self, NotificationCenter.default.addObserver(self,
selector:#selector(didBecomeActive), selector: #selector(didBecomeActive),
name:NSNotification.Name.OWSApplicationDidBecomeActive, name: NSNotification.Name.OWSApplicationDidBecomeActive,
object:nil) object: nil)
} }
deinit { deinit {
@ -202,8 +202,8 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
func createViews() { func createViews() {
self.view.isUserInteractionEnabled = true self.view.isUserInteractionEnabled = true
self.view.addGestureRecognizer(OWSAnyTouchGestureRecognizer(target:self, self.view.addGestureRecognizer(OWSAnyTouchGestureRecognizer(target: self,
action:#selector(didTouchRootView))) action: #selector(didTouchRootView)))
// Dark blurred background. // Dark blurred background.
let blurEffect = UIBlurEffect(style: .dark) let blurEffect = UIBlurEffect(style: .dark)
@ -252,7 +252,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
contactNameLabel.trailingBuffer = ScaleFromIPhone5(80.0) contactNameLabel.trailingBuffer = ScaleFromIPhone5(80.0)
// label config // label config
contactNameLabel.font = UIFont.ows_lightFont(withSize:ScaleFromIPhone5To7Plus(32, 40)) contactNameLabel.font = UIFont.ows_lightFont(withSize: ScaleFromIPhone5To7Plus(32, 40))
contactNameLabel.textColor = UIColor.white contactNameLabel.textColor = UIColor.white
contactNameLabel.layer.shadowOffset = CGSize.zero contactNameLabel.layer.shadowOffset = CGSize.zero
contactNameLabel.layer.shadowOpacity = 0.35 contactNameLabel.layer.shadowOpacity = 0.35
@ -261,7 +261,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
self.view.addSubview(contactNameLabel) self.view.addSubview(contactNameLabel)
callStatusLabel = UILabel() callStatusLabel = UILabel()
callStatusLabel.font = UIFont.ows_regularFont(withSize:ScaleFromIPhone5To7Plus(19, 25)) callStatusLabel.font = UIFont.ows_regularFont(withSize: ScaleFromIPhone5To7Plus(19, 25))
callStatusLabel.textColor = UIColor.white callStatusLabel.textColor = UIColor.white
callStatusLabel.layer.shadowOffset = CGSize.zero callStatusLabel.layer.shadowOffset = CGSize.zero
callStatusLabel.layer.shadowOpacity = 0.35 callStatusLabel.layer.shadowOpacity = 0.35
@ -287,41 +287,41 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
settingsNagDescriptionLabel = UILabel() settingsNagDescriptionLabel = UILabel()
settingsNagDescriptionLabel.text = NSLocalizedString("CALL_VIEW_SETTINGS_NAG_DESCRIPTION_ALL", settingsNagDescriptionLabel.text = NSLocalizedString("CALL_VIEW_SETTINGS_NAG_DESCRIPTION_ALL",
comment: "Reminder to the user of the benefits of enabling CallKit and disabling CallKit privacy.") comment: "Reminder to the user of the benefits of enabling CallKit and disabling CallKit privacy.")
settingsNagDescriptionLabel.font = UIFont.ows_regularFont(withSize:ScaleFromIPhone5To7Plus(16, 18)) settingsNagDescriptionLabel.font = UIFont.ows_regularFont(withSize: ScaleFromIPhone5To7Plus(16, 18))
settingsNagDescriptionLabel.textColor = UIColor.white settingsNagDescriptionLabel.textColor = UIColor.white
settingsNagDescriptionLabel.numberOfLines = 0 settingsNagDescriptionLabel.numberOfLines = 0
settingsNagDescriptionLabel.lineBreakMode = .byWordWrapping settingsNagDescriptionLabel.lineBreakMode = .byWordWrapping
viewStack.addSubview(settingsNagDescriptionLabel) viewStack.addSubview(settingsNagDescriptionLabel)
settingsNagDescriptionLabel.autoPinWidthToSuperview() settingsNagDescriptionLabel.autoPinWidthToSuperview()
settingsNagDescriptionLabel.autoPinEdge(toSuperviewEdge:.top) settingsNagDescriptionLabel.autoPinEdge(toSuperviewEdge: .top)
let buttonHeight = ScaleFromIPhone5To7Plus(35, 45) let buttonHeight = ScaleFromIPhone5To7Plus(35, 45)
let descriptionVSpacingHeight = ScaleFromIPhone5To7Plus(30, 60) let descriptionVSpacingHeight = ScaleFromIPhone5To7Plus(30, 60)
let callSettingsButton = OWSFlatButton.button(title:NSLocalizedString("CALL_VIEW_SETTINGS_NAG_SHOW_CALL_SETTINGS", let callSettingsButton = OWSFlatButton.button(title: NSLocalizedString("CALL_VIEW_SETTINGS_NAG_SHOW_CALL_SETTINGS",
comment: "Label for button that shows the privacy settings."), comment: "Label for button that shows the privacy settings."),
font:OWSFlatButton.fontForHeight(buttonHeight), font: OWSFlatButton.fontForHeight(buttonHeight),
titleColor:UIColor.white, titleColor: UIColor.white,
backgroundColor:UIColor.ows_signalBrandBlue, backgroundColor: UIColor.ows_signalBrandBlue,
target:self, target: self,
selector:#selector(didPressShowCallSettings)) selector: #selector(didPressShowCallSettings))
viewStack.addSubview(callSettingsButton) viewStack.addSubview(callSettingsButton)
callSettingsButton.autoSetDimension(.height, toSize:buttonHeight) callSettingsButton.autoSetDimension(.height, toSize: buttonHeight)
callSettingsButton.autoPinWidthToSuperview() callSettingsButton.autoPinWidthToSuperview()
callSettingsButton.autoPinEdge(.top, to:.bottom, of:settingsNagDescriptionLabel, withOffset:descriptionVSpacingHeight) callSettingsButton.autoPinEdge(.top, to: .bottom, of: settingsNagDescriptionLabel, withOffset: descriptionVSpacingHeight)
let notNowButton = OWSFlatButton.button(title:NSLocalizedString("CALL_VIEW_SETTINGS_NAG_NOT_NOW_BUTTON", let notNowButton = OWSFlatButton.button(title: NSLocalizedString("CALL_VIEW_SETTINGS_NAG_NOT_NOW_BUTTON",
comment: "Label for button that dismiss the call view's settings nag."), comment: "Label for button that dismiss the call view's settings nag."),
font:OWSFlatButton.fontForHeight(buttonHeight), font: OWSFlatButton.fontForHeight(buttonHeight),
titleColor:UIColor.white, titleColor: UIColor.white,
backgroundColor:UIColor.ows_signalBrandBlue, backgroundColor: UIColor.ows_signalBrandBlue,
target:self, target: self,
selector:#selector(didPressDismissNag)) selector: #selector(didPressDismissNag))
viewStack.addSubview(notNowButton) viewStack.addSubview(notNowButton)
notNowButton.autoSetDimension(.height, toSize:buttonHeight) notNowButton.autoSetDimension(.height, toSize: buttonHeight)
notNowButton.autoPinWidthToSuperview() notNowButton.autoPinWidthToSuperview()
notNowButton.autoPinEdge(toSuperviewEdge:.bottom) notNowButton.autoPinEdge(toSuperviewEdge: .bottom)
notNowButton.autoPinEdge(.top, to:.bottom, of:callSettingsButton, withOffset:12) notNowButton.autoPinEdge(.top, to: .bottom, of: callSettingsButton, withOffset: 12)
} }
func buttonSize() -> CGFloat { func buttonSize() -> CGFloat {
@ -336,31 +336,31 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
// textMessageButton = createButton(imageName:"message-active-wide", // textMessageButton = createButton(imageName:"message-active-wide",
// action:#selector(didPressTextMessage)) // action:#selector(didPressTextMessage))
audioSourceButton = createButton(imageName:"audio-call-speaker-inactive", audioSourceButton = createButton(imageName: "audio-call-speaker-inactive",
action:#selector(didPressAudioSource)) action: #selector(didPressAudioSource))
audioSourceButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_AUDIO_SOURCE_LABEL", audioSourceButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_AUDIO_SOURCE_LABEL",
comment: "Accessibility label for selection the audio source") comment: "Accessibility label for selection the audio source")
hangUpButton = createButton(imageName:"hangup-active-wide", hangUpButton = createButton(imageName: "hangup-active-wide",
action:#selector(didPressHangup)) action: #selector(didPressHangup))
hangUpButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_HANGUP_LABEL", hangUpButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_HANGUP_LABEL",
comment: "Accessibility label for hang up call") comment: "Accessibility label for hang up call")
audioModeMuteButton = createButton(imageName:"audio-call-mute-inactive", audioModeMuteButton = createButton(imageName: "audio-call-mute-inactive",
action:#selector(didPressMute)) action: #selector(didPressMute))
audioModeMuteButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_MUTE_LABEL", audioModeMuteButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_MUTE_LABEL",
comment: "Accessibility label for muting the microphone") comment: "Accessibility label for muting the microphone")
videoModeMuteButton = createButton(imageName:"video-mute-unselected", videoModeMuteButton = createButton(imageName: "video-mute-unselected",
action:#selector(didPressMute)) action: #selector(didPressMute))
videoModeMuteButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_MUTE_LABEL", comment: "Accessibility label for muting the microphone") videoModeMuteButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_MUTE_LABEL", comment: "Accessibility label for muting the microphone")
audioModeVideoButton = createButton(imageName:"audio-call-video-inactive", audioModeVideoButton = createButton(imageName: "audio-call-video-inactive",
action:#selector(didPressVideo)) action: #selector(didPressVideo))
audioModeVideoButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_SWITCH_TO_VIDEO_LABEL", comment: "Accessibility label to switch to video call") audioModeVideoButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_SWITCH_TO_VIDEO_LABEL", comment: "Accessibility label to switch to video call")
videoModeVideoButton = createButton(imageName:"video-video-unselected", videoModeVideoButton = createButton(imageName: "video-video-unselected",
action:#selector(didPressVideo)) action: #selector(didPressVideo))
videoModeVideoButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_SWITCH_TO_AUDIO_LABEL", comment: "Accessibility label to switch to audio only") videoModeVideoButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_SWITCH_TO_AUDIO_LABEL", comment: "Accessibility label to switch to audio only")
setButtonSelectedImage(button: audioModeMuteButton, imageName: "audio-call-mute-active") setButtonSelectedImage(button: audioModeMuteButton, imageName: "audio-call-mute-active")
@ -368,7 +368,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
setButtonSelectedImage(button: audioModeVideoButton, imageName: "audio-call-video-active") setButtonSelectedImage(button: audioModeVideoButton, imageName: "audio-call-video-active")
setButtonSelectedImage(button: videoModeVideoButton, imageName: "video-video-selected") setButtonSelectedImage(button: videoModeVideoButton, imageName: "video-video-selected")
ongoingCallView = createContainerForCallControls(controlGroups : [ ongoingCallView = createContainerForCallControls(controlGroups: [
[audioModeMuteButton, audioSourceButton, audioModeVideoButton ], [audioModeMuteButton, audioSourceButton, audioModeVideoButton ],
[videoModeMuteButton, hangUpButton, videoModeVideoButton ] [videoModeMuteButton, hangUpButton, videoModeVideoButton ]
]) ])
@ -379,7 +379,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
let actionSheetController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) let actionSheetController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let dismissAction = UIAlertAction(title: CommonStrings.dismissButton, style: .cancel, handler: nil) let dismissAction = UIAlertAction(title: CommonStrings.dismissButton, style: .cancel, handler: nil)
actionSheetController.addAction(dismissAction) actionSheetController.addAction(dismissAction)
let currentAudioSource = callUIAdapter.audioService.currentAudioSource(call: self.call) let currentAudioSource = callUIAdapter.audioService.currentAudioSource(call: self.call)
@ -402,9 +402,9 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
} }
func setButtonSelectedImage(button: UIButton, imageName: String) { func setButtonSelectedImage(button: UIButton, imageName: String) {
let image = UIImage(named:imageName) let image = UIImage(named: imageName)
assert(image != nil) assert(image != nil)
button.setImage(image, for:.selected) button.setImage(image, for: .selected)
} }
func updateAvatarImage() { func updateAvatarImage() {
@ -413,16 +413,16 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
func createIncomingCallControls() { func createIncomingCallControls() {
acceptIncomingButton = createButton(imageName:"call-active-wide", acceptIncomingButton = createButton(imageName: "call-active-wide",
action:#selector(didPressAnswerCall)) action: #selector(didPressAnswerCall))
acceptIncomingButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_ACCEPT_INCOMING_CALL_LABEL", acceptIncomingButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_ACCEPT_INCOMING_CALL_LABEL",
comment: "Accessibility label for accepting incoming calls") comment: "Accessibility label for accepting incoming calls")
declineIncomingButton = createButton(imageName:"hangup-active-wide", declineIncomingButton = createButton(imageName: "hangup-active-wide",
action:#selector(didPressDeclineCall)) action: #selector(didPressDeclineCall))
declineIncomingButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_DECLINE_INCOMING_CALL_LABEL", declineIncomingButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_DECLINE_INCOMING_CALL_LABEL",
comment: "Accessibility label for declining incoming calls") comment: "Accessibility label for declining incoming calls")
incomingCallView = createContainerForCallControls(controlGroups : [ incomingCallView = createContainerForCallControls(controlGroups: [
[acceptIncomingButton, declineIncomingButton ] [acceptIncomingButton, declineIncomingButton ]
]) ])
} }
@ -432,7 +432,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
self.view.addSubview(containerView) self.view.addSubview(containerView)
var rows: [UIView] = [] var rows: [UIView] = []
for controlGroup in controlGroups { for controlGroup in controlGroups {
rows.append(rowWithSubviews(subviews:controlGroup)) rows.append(rowWithSubviews(subviews: controlGroup))
} }
let rowspacing = ScaleFromIPhone5To7Plus(6, 7) let rowspacing = ScaleFromIPhone5To7Plus(6, 7)
var prevRow: UIView? var prevRow: UIView?
@ -440,29 +440,29 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
containerView.addSubview(row) containerView.addSubview(row)
row.autoHCenterInSuperview() row.autoHCenterInSuperview()
if prevRow != nil { if prevRow != nil {
row.autoPinEdge(.top, to:.bottom, of:prevRow!, withOffset:rowspacing) row.autoPinEdge(.top, to: .bottom, of: prevRow!, withOffset: rowspacing)
} }
prevRow = row prevRow = row
} }
containerView.setContentHuggingVerticalHigh() containerView.setContentHuggingVerticalHigh()
rows.first!.autoPinEdge(toSuperviewEdge:.top) rows.first!.autoPinEdge(toSuperviewEdge: .top)
rows.last!.autoPinEdge(toSuperviewEdge:.bottom) rows.last!.autoPinEdge(toSuperviewEdge: .bottom)
return containerView return containerView
} }
func createButton(imageName: String, action: Selector) -> UIButton { func createButton(imageName: String, action: Selector) -> UIButton {
let image = UIImage(named:imageName) let image = UIImage(named: imageName)
assert(image != nil) assert(image != nil)
let button = UIButton() let button = UIButton()
button.setImage(image, for:.normal) button.setImage(image, for: .normal)
button.imageEdgeInsets = UIEdgeInsets(top: buttonInset(), button.imageEdgeInsets = UIEdgeInsets(top: buttonInset(),
left: buttonInset(), left: buttonInset(),
bottom: buttonInset(), bottom: buttonInset(),
right: buttonInset()) right: buttonInset())
button.addTarget(self, action:action, for:.touchUpInside) button.addTarget(self, action: action, for: .touchUpInside)
button.autoSetDimension(.width, toSize:buttonSize()) button.autoSetDimension(.width, toSize: buttonSize())
button.autoSetDimension(.height, toSize:buttonSize()) button.autoSetDimension(.height, toSize: buttonSize())
return button return button
} }
@ -470,7 +470,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
func rowWithSubviews(subviews: [UIView]) -> UIView { func rowWithSubviews(subviews: [UIView]) -> UIView {
let row = UIView() let row = UIView()
row.setContentHuggingVerticalHigh() row.setContentHuggingVerticalHigh()
row.autoSetDimension(.height, toSize:buttonSize()) row.autoSetDimension(.height, toSize: buttonSize())
if subviews.count > 1 { if subviews.count > 1 {
// If there's more than one subview in the row, // If there's more than one subview in the row,
@ -485,8 +485,8 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
let spacer = UIView() let spacer = UIView()
spacer.isHidden = true spacer.isHidden = true
row.addSubview(spacer) row.addSubview(spacer)
spacer.autoPinEdge(.left, to:.right, of:lastSubview!) spacer.autoPinEdge(.left, to: .right, of: lastSubview!)
spacer.autoPinEdge(.right, to:.left, of:subview) spacer.autoPinEdge(.right, to: .left, of: subview)
spacer.setContentHuggingHorizontalLow() spacer.setContentHuggingHorizontalLow()
spacer.autoVCenterInSuperview() spacer.autoVCenterInSuperview()
@ -500,8 +500,8 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
lastSubview = subview lastSubview = subview
} }
subviews.first!.autoPinEdge(toSuperviewEdge:.left) subviews.first!.autoPinEdge(toSuperviewEdge: .left)
subviews.last!.autoPinEdge(toSuperviewEdge:.right) subviews.last!.autoPinEdge(toSuperviewEdge: .right)
} else if subviews.count == 1 { } else if subviews.count == 1 {
// If there's only one subview in this row, center it. // If there's only one subview in this row, center it.
let subview = subviews.first! let subview = subviews.first!
@ -544,25 +544,25 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
blurView.autoPinEdgesToSuperviewEdges() blurView.autoPinEdgesToSuperviewEdges()
localVideoView.autoPinTrailingToSuperview(withMargin: videoPreviewHMargin) localVideoView.autoPinTrailingToSuperview(withMargin: videoPreviewHMargin)
localVideoView.autoPinEdge(toSuperviewEdge:.top, withInset:topMargin) localVideoView.autoPinEdge(toSuperviewEdge: .top, withInset: topMargin)
let localVideoSize = ScaleFromIPhone5To7Plus(80, 100) let localVideoSize = ScaleFromIPhone5To7Plus(80, 100)
localVideoView.autoSetDimension(.width, toSize:localVideoSize) localVideoView.autoSetDimension(.width, toSize: localVideoSize)
localVideoView.autoSetDimension(.height, toSize:localVideoSize) localVideoView.autoSetDimension(.height, toSize: localVideoSize)
remoteVideoView.autoPinEdgesToSuperviewEdges() remoteVideoView.autoPinEdgesToSuperviewEdges()
contactNameLabel.autoPinEdge(toSuperviewEdge:.top, withInset:topMargin) contactNameLabel.autoPinEdge(toSuperviewEdge: .top, withInset: topMargin)
contactNameLabel.autoPinLeadingToSuperview(withMargin: contactHMargin) contactNameLabel.autoPinLeadingToSuperview(withMargin: contactHMargin)
contactNameLabel.setContentHuggingVerticalHigh() contactNameLabel.setContentHuggingVerticalHigh()
contactNameLabel.setCompressionResistanceHigh() contactNameLabel.setCompressionResistanceHigh()
callStatusLabel.autoPinEdge(.top, to:.bottom, of:contactNameLabel, withOffset:contactVSpacing) callStatusLabel.autoPinEdge(.top, to: .bottom, of: contactNameLabel, withOffset: contactVSpacing)
callStatusLabel.autoPinLeadingToSuperview(withMargin: contactHMargin) callStatusLabel.autoPinLeadingToSuperview(withMargin: contactHMargin)
callStatusLabel.setContentHuggingVerticalHigh() callStatusLabel.setContentHuggingVerticalHigh()
callStatusLabel.setCompressionResistanceHigh() callStatusLabel.setCompressionResistanceHigh()
contactAvatarContainerView.autoPinEdge(.top, to:.bottom, of:callStatusLabel, withOffset:+avatarTopSpacing) contactAvatarContainerView.autoPinEdge(.top, to: .bottom, of: callStatusLabel, withOffset: +avatarTopSpacing)
contactAvatarContainerView.autoPinEdge(.bottom, to:.top, of:ongoingCallView, withOffset:-avatarBottomSpacing) contactAvatarContainerView.autoPinEdge(.bottom, to: .top, of: ongoingCallView, withOffset: -avatarBottomSpacing)
contactAvatarContainerView.autoPinWidthToSuperview(withMargin: avatarTopSpacing) contactAvatarContainerView.autoPinWidthToSuperview(withMargin: avatarTopSpacing)
contactAvatarView.autoCenterInSuperview() contactAvatarView.autoCenterInSuperview()
@ -579,19 +579,19 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
} }
// Ongoing call controls // Ongoing call controls
ongoingCallView.autoPinEdge(toSuperviewEdge:.bottom, withInset:ongoingBottomMargin) ongoingCallView.autoPinEdge(toSuperviewEdge: .bottom, withInset: ongoingBottomMargin)
ongoingCallView.autoPinWidthToSuperview(withMargin:ongoingHMargin) ongoingCallView.autoPinWidthToSuperview(withMargin: ongoingHMargin)
ongoingCallView.setContentHuggingVerticalHigh() ongoingCallView.setContentHuggingVerticalHigh()
// Incoming call controls // Incoming call controls
incomingCallView.autoPinEdge(toSuperviewEdge:.bottom, withInset:incomingBottomMargin) incomingCallView.autoPinEdge(toSuperviewEdge: .bottom, withInset: incomingBottomMargin)
incomingCallView.autoPinWidthToSuperview(withMargin:incomingHMargin) incomingCallView.autoPinWidthToSuperview(withMargin: incomingHMargin)
incomingCallView.setContentHuggingVerticalHigh() incomingCallView.setContentHuggingVerticalHigh()
// Settings nag views // Settings nag views
settingsNagView.autoPinEdge(toSuperviewEdge:.bottom, withInset:settingsNagBottomMargin) settingsNagView.autoPinEdge(toSuperviewEdge: .bottom, withInset: settingsNagBottomMargin)
settingsNagView.autoPinWidthToSuperview(withMargin:settingsNagHMargin) settingsNagView.autoPinWidthToSuperview(withMargin: settingsNagHMargin)
settingsNagView.autoPinEdge(.top, to:.bottom, of:callStatusLabel) settingsNagView.autoPinEdge(.top, to: .bottom, of: callStatusLabel)
} }
updateRemoteVideoLayout() updateRemoteVideoLayout()
@ -648,11 +648,11 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
return NSLocalizedString("IN_CALL_SECURING", comment: "Call setup status label") return NSLocalizedString("IN_CALL_SECURING", comment: "Call setup status label")
case .connected: case .connected:
let callDuration = call.connectionDuration() let callDuration = call.connectionDuration()
let callDurationDate = Date(timeIntervalSinceReferenceDate:callDuration) let callDurationDate = Date(timeIntervalSinceReferenceDate: callDuration)
if dateFormatter == nil { if dateFormatter == nil {
dateFormatter = DateFormatter() dateFormatter = DateFormatter()
dateFormatter!.dateFormat = "HH:mm:ss" dateFormatter!.dateFormat = "HH:mm:ss"
dateFormatter!.timeZone = TimeZone(identifier:"UTC")! dateFormatter!.timeZone = TimeZone(identifier: "UTC")!
} }
var formattedDate = dateFormatter!.string(from: callDurationDate) var formattedDate = dateFormatter!.string(from: callDurationDate)
if formattedDate.hasPrefix("00:") { if formattedDate.hasPrefix("00:") {
@ -771,10 +771,10 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
switch callState { switch callState {
case .remoteHangup, .remoteBusy, .localFailure: case .remoteHangup, .remoteBusy, .localFailure:
Logger.debug("\(TAG) dismissing after delay because new state is \(callState)") Logger.debug("\(TAG) dismissing after delay because new state is \(callState)")
dismissIfPossible(shouldDelay:true) dismissIfPossible(shouldDelay: true)
case .localHangup: case .localHangup:
Logger.debug("\(TAG) dismissing immediately from local hangup") Logger.debug("\(TAG) dismissing immediately from local hangup")
dismissIfPossible(shouldDelay:false) dismissIfPossible(shouldDelay: false)
default: break default: break
} }
@ -782,9 +782,9 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
if callDurationTimer == nil { if callDurationTimer == nil {
let kDurationUpdateFrequencySeconds = 1 / 20.0 let kDurationUpdateFrequencySeconds = 1 / 20.0
callDurationTimer = WeakTimer.scheduledTimer(timeInterval: TimeInterval(kDurationUpdateFrequencySeconds), callDurationTimer = WeakTimer.scheduledTimer(timeInterval: TimeInterval(kDurationUpdateFrequencySeconds),
target:self, target: self,
userInfo:nil, userInfo: nil,
repeats:true) {[weak self] _ in repeats: true) {[weak self] _ in
self?.updateCallDuration() self?.updateCallDuration()
} }
} }
@ -831,7 +831,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
callUIAdapter.localHangupCall(call) callUIAdapter.localHangupCall(call)
dismissIfPossible(shouldDelay:false) dismissIfPossible(shouldDelay: false)
} }
func didPressMute(sender muteButton: UIButton) { func didPressMute(sender muteButton: UIButton) {
@ -861,7 +861,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
func didPressTextMessage(sender button: UIButton) { func didPressTextMessage(sender button: UIButton) {
Logger.info("\(TAG) called \(#function)") Logger.info("\(TAG) called \(#function)")
dismissIfPossible(shouldDelay:false) dismissIfPossible(shouldDelay: false)
} }
func didPressAnswerCall(sender: UIButton) { func didPressAnswerCall(sender: UIButton) {
@ -885,7 +885,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
callUIAdapter.declineCall(call) callUIAdapter.declineCall(call)
dismissIfPossible(shouldDelay:false) dismissIfPossible(shouldDelay: false)
} }
func didPressShowCallSettings(sender: UIButton) { func didPressShowCallSettings(sender: UIButton) {
@ -901,7 +901,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
// Construct the "settings" view & push the "privacy settings" view. // Construct the "settings" view & push the "privacy settings" view.
let navigationController = AppSettingsViewController.inModalNavigationController() let navigationController = AppSettingsViewController.inModalNavigationController()
navigationController.pushViewController(PrivacySettingsTableViewController(), animated:false) navigationController.pushViewController(PrivacySettingsTableViewController(), animated: false)
fromViewController?.present(navigationController, animated: true, completion: nil) fromViewController?.present(navigationController, animated: true, completion: nil)
}) })
@ -1022,7 +1022,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
updateRemoteVideoLayout() updateRemoteVideoLayout()
} }
internal func dismissIfPossible(shouldDelay: Bool, ignoreNag ignoreNagParam: Bool = false, completion: (() -> Swift.Void)? = nil) { internal func dismissIfPossible(shouldDelay: Bool, ignoreNag ignoreNagParam: Bool = false, completion: (() -> Void)? = nil) {
callUIAdapter.audioService.delegate = nil callUIAdapter.audioService.delegate = nil
let ignoreNag: Bool = { let ignoreNag: Bool = {
@ -1071,11 +1071,11 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
hasDismissed = true hasDismissed = true
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [weak self] in DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [weak self] in
guard let strongSelf = self else { return } guard let strongSelf = self else { return }
strongSelf.dismiss(animated: true, completion:completion) strongSelf.dismiss(animated: true, completion: completion)
} }
} else { } else {
hasDismissed = true hasDismissed = true
self.dismiss(animated: false, completion:completion) self.dismiss(animated: false, completion: completion)
} }
} }

@ -194,10 +194,10 @@ enum GiphyAssetRequestState: UInt {
redundantLength = segmentStart + segmentLength - contentLength redundantLength = segmentStart + segmentLength - contentLength
segmentStart = contentLength - segmentLength segmentStart = contentLength - segmentLength
} }
let assetSegment = GiphyAssetSegment(index:index, let assetSegment = GiphyAssetSegment(index: index,
segmentStart:segmentStart, segmentStart: segmentStart,
segmentLength:segmentLength, segmentLength: segmentLength,
redundantLength:redundantLength) redundantLength: redundantLength)
segments.append(assetSegment) segments.append(assetSegment)
nextSegmentStart = segmentStart + segmentLength nextSegmentStart = segmentStart + segmentLength
index += 1 index += 1
@ -222,7 +222,7 @@ enum GiphyAssetRequestState: UInt {
public func firstWaitingSegment() -> GiphyAssetSegment? { public func firstWaitingSegment() -> GiphyAssetSegment? {
AssertIsOnMainThread() AssertIsOnMainThread()
return firstSegmentWithState(state:.waiting) return firstSegmentWithState(state: .waiting)
} }
public func downloadingSegmentsCount() -> UInt { public func downloadingSegmentsCount() -> UInt {
@ -287,8 +287,8 @@ enum GiphyAssetRequestState: UInt {
Logger.verbose("\(TAG) filePath: \(filePath).") Logger.verbose("\(TAG) filePath: \(filePath).")
do { do {
try assetData.write(to: NSURL.fileURL(withPath:filePath), options: .atomicWrite) try assetData.write(to: NSURL.fileURL(withPath: filePath), options: .atomicWrite)
let asset = GiphyAsset(rendition: rendition, filePath : filePath) let asset = GiphyAsset(rendition: rendition, filePath: filePath)
return asset return asset
} catch let error as NSError { } catch let error as NSError {
owsFail("\(GiphyAsset.TAG) file write failed: \(filePath), \(error)") owsFail("\(GiphyAsset.TAG) file write failed: \(filePath), \(error)")
@ -360,7 +360,7 @@ enum GiphyAssetRequestState: UInt {
DispatchQueue.global().async { DispatchQueue.global().async {
do { do {
let fileManager = FileManager.default let fileManager = FileManager.default
try fileManager.removeItem(atPath:filePathCopy) try fileManager.removeItem(atPath: filePathCopy)
} catch let error as NSError { } catch let error as NSError {
owsFail("\(GiphyAsset.TAG) file cleanup failed: \(filePathCopy), \(error)") owsFail("\(GiphyAsset.TAG) file cleanup failed: \(filePathCopy), \(error)")
} }
@ -406,7 +406,7 @@ class LRUCache<KeyType: Hashable & Equatable, ValueType> {
return return
} }
cacheOrder.removeFirst() cacheOrder.removeFirst()
cacheMap.removeValue(forKey:staleKey) cacheMap.removeValue(forKey: staleKey)
} }
} }
} }
@ -468,9 +468,9 @@ extension URLSessionTask {
configuration.urlCache = nil configuration.urlCache = nil
configuration.requestCachePolicy = .reloadIgnoringCacheData configuration.requestCachePolicy = .reloadIgnoringCacheData
configuration.httpMaximumConnectionsPerHost = 10 configuration.httpMaximumConnectionsPerHost = 10
let session = URLSession(configuration:configuration, let session = URLSession(configuration: configuration,
delegate:self, delegate: self,
delegateQueue:nil) delegateQueue: nil)
return session return session
}() }()
@ -481,7 +481,7 @@ extension URLSessionTask {
// evacuated from the cache; if a cache consumer (e.g. view) is // evacuated from the cache; if a cache consumer (e.g. view) is
// still using the asset, the asset won't be deleted on disk until // still using the asset, the asset won't be deleted on disk until
// it is no longer in use. // it is no longer in use.
private var assetMap = LRUCache<NSURL, GiphyAsset>(maxSize:100) private var assetMap = LRUCache<NSURL, GiphyAsset>(maxSize: 100)
// TODO: We could use a proper queue, e.g. implemented with a linked // TODO: We could use a proper queue, e.g. implemented with a linked
// list. // list.
private var assetRequestQueue = [GiphyAssetRequest]() private var assetRequestQueue = [GiphyAssetRequest]()
@ -496,7 +496,7 @@ extension URLSessionTask {
failure:@escaping ((GiphyAssetRequest) -> Void)) -> GiphyAssetRequest? { failure:@escaping ((GiphyAssetRequest) -> Void)) -> GiphyAssetRequest? {
AssertIsOnMainThread() AssertIsOnMainThread()
if let asset = assetMap.get(key:rendition.url) { if let asset = assetMap.get(key: rendition.url) {
// Synchronous cache hit. // Synchronous cache hit.
Logger.verbose("\(self.TAG) asset cache hit: \(rendition.url)") Logger.verbose("\(self.TAG) asset cache hit: \(rendition.url)")
success(nil, asset) success(nil, asset)
@ -507,10 +507,10 @@ extension URLSessionTask {
// //
// Asset requests are done queued and performed asynchronously. // Asset requests are done queued and performed asynchronously.
Logger.verbose("\(self.TAG) asset cache miss: \(rendition.url)") Logger.verbose("\(self.TAG) asset cache miss: \(rendition.url)")
let assetRequest = GiphyAssetRequest(rendition:rendition, let assetRequest = GiphyAssetRequest(rendition: rendition,
priority:priority, priority: priority,
success:success, success: success,
failure:failure) failure: failure)
assetRequestQueue.append(assetRequest) assetRequestQueue.append(assetRequest)
// Process the queue (which may start this request) // Process the queue (which may start this request)
// asynchronously so that the caller has time to store // asynchronously so that the caller has time to store
@ -540,8 +540,8 @@ extension URLSessionTask {
// Move write off main thread. // Move write off main thread.
DispatchQueue.global().async { DispatchQueue.global().async {
guard let asset = assetRequest.writeAssetToFile(gifFolderPath:self.gifFolderPath) else { guard let asset = assetRequest.writeAssetToFile(gifFolderPath: self.gifFolderPath) else {
self.segmentRequestDidFail(assetRequest:assetRequest, assetSegment:assetSegment) self.segmentRequestDidFail(assetRequest: assetRequest, assetSegment: assetSegment)
return return
} }
self.assetRequestDidSucceed(assetRequest: assetRequest, asset: asset) self.assetRequestDidSucceed(assetRequest: assetRequest, asset: asset)
@ -555,9 +555,9 @@ extension URLSessionTask {
private func assetRequestDidSucceed(assetRequest: GiphyAssetRequest, asset: GiphyAsset) { private func assetRequestDidSucceed(assetRequest: GiphyAssetRequest, asset: GiphyAsset) {
DispatchQueue.main.async { DispatchQueue.main.async {
self.assetMap.set(key:assetRequest.rendition.url, value:asset) self.assetMap.set(key: assetRequest.rendition.url, value: asset)
self.removeAssetRequestFromQueue(assetRequest:assetRequest) self.removeAssetRequestFromQueue(assetRequest: assetRequest)
assetRequest.requestDidSucceed(asset:asset) assetRequest.requestDidSucceed(asset: asset)
} }
} }
@ -567,14 +567,14 @@ extension URLSessionTask {
DispatchQueue.main.async { DispatchQueue.main.async {
assetSegment.state = .failed assetSegment.state = .failed
assetRequest.state = .failed assetRequest.state = .failed
self.assetRequestDidFail(assetRequest:assetRequest) self.assetRequestDidFail(assetRequest: assetRequest)
} }
} }
private func assetRequestDidFail(assetRequest: GiphyAssetRequest) { private func assetRequestDidFail(assetRequest: GiphyAssetRequest) {
DispatchQueue.main.async { DispatchQueue.main.async {
self.removeAssetRequestFromQueue(assetRequest:assetRequest) self.removeAssetRequestFromQueue(assetRequest: assetRequest)
assetRequest.requestDidFail() assetRequest.requestDidFail()
} }
} }
@ -616,17 +616,17 @@ extension URLSessionTask {
guard UIApplication.shared.applicationState == .active else { guard UIApplication.shared.applicationState == .active else {
// If app is not active, fail the asset request. // If app is not active, fail the asset request.
assetRequest.state = .failed assetRequest.state = .failed
assetRequestDidFail(assetRequest:assetRequest) assetRequestDidFail(assetRequest: assetRequest)
processRequestQueueSync() processRequestQueueSync()
return return
} }
if let asset = assetMap.get(key:assetRequest.rendition.url) { if let asset = assetMap.get(key: assetRequest.rendition.url) {
// Deferred cache hit, avoids re-downloading assets that were // Deferred cache hit, avoids re-downloading assets that were
// downloaded while this request was queued. // downloaded while this request was queued.
assetRequest.state = .complete assetRequest.state = .complete
assetRequestDidSucceed(assetRequest : assetRequest, asset: asset) assetRequestDidSucceed(assetRequest: assetRequest, asset: asset)
return return
} }
@ -639,11 +639,11 @@ extension URLSessionTask {
request.httpMethod = "HEAD" request.httpMethod = "HEAD"
request.httpShouldUsePipelining = true request.httpShouldUsePipelining = true
let task = giphyDownloadSession.dataTask(with:request, completionHandler: { data, response, error -> Void in let task = giphyDownloadSession.dataTask(with: request, completionHandler: { data, response, error -> Void in
if let data = data, data.count > 0 { if let data = data, data.count > 0 {
owsFail("\(self.TAG) HEAD request has unexpected body: \(data.count).") owsFail("\(self.TAG) HEAD request has unexpected body: \(data.count).")
} }
self.handleAssetSizeResponse(assetRequest:assetRequest, response:response, error:error) self.handleAssetSizeResponse(assetRequest: assetRequest, response: response, error: error)
}) })
assetRequest.contentLengthTask = task assetRequest.contentLengthTask = task
task.resume() task.resume()
@ -660,7 +660,7 @@ extension URLSessionTask {
request.httpShouldUsePipelining = true request.httpShouldUsePipelining = true
let rangeHeaderValue = "bytes=\(assetSegment.segmentStart)-\(assetSegment.segmentStart + assetSegment.segmentLength - 1)" let rangeHeaderValue = "bytes=\(assetSegment.segmentStart)-\(assetSegment.segmentStart + assetSegment.segmentLength - 1)"
request.addValue(rangeHeaderValue, forHTTPHeaderField: "Range") request.addValue(rangeHeaderValue, forHTTPHeaderField: "Range")
let task = giphyDownloadSession.dataTask(with:request) let task = giphyDownloadSession.dataTask(with: request)
task.assetRequest = assetRequest task.assetRequest = assetRequest
task.assetSegment = assetSegment task.assetSegment = assetSegment
assetSegment.task = task assetSegment.task = task
@ -674,31 +674,31 @@ extension URLSessionTask {
private func handleAssetSizeResponse(assetRequest: GiphyAssetRequest, response: URLResponse?, error: Error?) { private func handleAssetSizeResponse(assetRequest: GiphyAssetRequest, response: URLResponse?, error: Error?) {
guard error == nil else { guard error == nil else {
assetRequest.state = .failed assetRequest.state = .failed
self.assetRequestDidFail(assetRequest:assetRequest) self.assetRequestDidFail(assetRequest: assetRequest)
return return
} }
guard let httpResponse = response as? HTTPURLResponse else { guard let httpResponse = response as? HTTPURLResponse else {
owsFail("\(self.TAG) Asset size response is invalid.") owsFail("\(self.TAG) Asset size response is invalid.")
assetRequest.state = .failed assetRequest.state = .failed
self.assetRequestDidFail(assetRequest:assetRequest) self.assetRequestDidFail(assetRequest: assetRequest)
return return
} }
guard let contentLengthString = httpResponse.allHeaderFields["Content-Length"] as? String else { guard let contentLengthString = httpResponse.allHeaderFields["Content-Length"] as? String else {
owsFail("\(self.TAG) Asset size response is missing content length.") owsFail("\(self.TAG) Asset size response is missing content length.")
assetRequest.state = .failed assetRequest.state = .failed
self.assetRequestDidFail(assetRequest:assetRequest) self.assetRequestDidFail(assetRequest: assetRequest)
return return
} }
guard let contentLength = Int(contentLengthString) else { guard let contentLength = Int(contentLengthString) else {
owsFail("\(self.TAG) Asset size response has unparsable content length.") owsFail("\(self.TAG) Asset size response has unparsable content length.")
assetRequest.state = .failed assetRequest.state = .failed
self.assetRequestDidFail(assetRequest:assetRequest) self.assetRequestDidFail(assetRequest: assetRequest)
return return
} }
guard contentLength > 0 else { guard contentLength > 0 else {
owsFail("\(self.TAG) Asset size response has invalid content length.") owsFail("\(self.TAG) Asset size response has invalid content length.")
assetRequest.state = .failed assetRequest.state = .failed
self.assetRequestDidFail(assetRequest:assetRequest) self.assetRequestDidFail(assetRequest: assetRequest)
return return
} }
@ -777,13 +777,13 @@ extension URLSessionTask {
let assetSegment = dataTask.assetSegment let assetSegment = dataTask.assetSegment
guard !assetRequest.wasCancelled else { guard !assetRequest.wasCancelled else {
dataTask.cancel() dataTask.cancel()
segmentRequestDidFail(assetRequest:assetRequest, assetSegment:assetSegment) segmentRequestDidFail(assetRequest: assetRequest, assetSegment: assetSegment)
return return
} }
assetSegment.append(data:data) assetSegment.append(data: data)
} }
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: @escaping (CachedURLResponse?) -> Swift.Void) { public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: @escaping (CachedURLResponse?) -> Void) {
completionHandler(nil) completionHandler(nil)
} }
@ -795,32 +795,32 @@ extension URLSessionTask {
let assetSegment = task.assetSegment let assetSegment = task.assetSegment
guard !assetRequest.wasCancelled else { guard !assetRequest.wasCancelled else {
task.cancel() task.cancel()
segmentRequestDidFail(assetRequest:assetRequest, assetSegment:assetSegment) segmentRequestDidFail(assetRequest: assetRequest, assetSegment: assetSegment)
return return
} }
if let error = error { if let error = error {
Logger.error("\(TAG) download failed with error: \(error)") Logger.error("\(TAG) download failed with error: \(error)")
segmentRequestDidFail(assetRequest:assetRequest, assetSegment:assetSegment) segmentRequestDidFail(assetRequest: assetRequest, assetSegment: assetSegment)
return return
} }
guard let httpResponse = task.response as? HTTPURLResponse else { guard let httpResponse = task.response as? HTTPURLResponse else {
Logger.error("\(TAG) missing or unexpected response: \(String(describing: task.response))") Logger.error("\(TAG) missing or unexpected response: \(String(describing: task.response))")
segmentRequestDidFail(assetRequest:assetRequest, assetSegment:assetSegment) segmentRequestDidFail(assetRequest: assetRequest, assetSegment: assetSegment)
return return
} }
let statusCode = httpResponse.statusCode let statusCode = httpResponse.statusCode
guard statusCode >= 200 && statusCode < 400 else { guard statusCode >= 200 && statusCode < 400 else {
Logger.error("\(TAG) response has invalid status code: \(statusCode)") Logger.error("\(TAG) response has invalid status code: \(statusCode)")
segmentRequestDidFail(assetRequest:assetRequest, assetSegment:assetSegment) segmentRequestDidFail(assetRequest: assetRequest, assetSegment: assetSegment)
return return
} }
guard assetSegment.totalDataSize() == assetSegment.segmentLength else { guard assetSegment.totalDataSize() == assetSegment.segmentLength else {
Logger.error("\(TAG) segment is missing data: \(statusCode)") Logger.error("\(TAG) segment is missing data: \(statusCode)")
segmentRequestDidFail(assetRequest:assetRequest, assetSegment:assetSegment) segmentRequestDidFail(assetRequest: assetRequest, assetSegment: assetSegment)
return return
} }
segmentRequestDidSucceed(assetRequest : assetRequest, assetSegment: assetSegment) segmentRequestDidSucceed(assetRequest: assetRequest, assetSegment: assetSegment)
} }
// MARK: Temp Directory // MARK: Temp Directory
@ -835,20 +835,20 @@ extension URLSessionTask {
let fileManager = FileManager.default let fileManager = FileManager.default
// Try to delete existing folder if necessary. // Try to delete existing folder if necessary.
if fileManager.fileExists(atPath:dirPath) { if fileManager.fileExists(atPath: dirPath) {
try fileManager.removeItem(atPath:dirPath) try fileManager.removeItem(atPath: dirPath)
gifFolderPath = dirPath gifFolderPath = dirPath
} }
// Try to create folder if necessary. // Try to create folder if necessary.
if !fileManager.fileExists(atPath:dirPath) { if !fileManager.fileExists(atPath: dirPath) {
try fileManager.createDirectory(atPath:dirPath, try fileManager.createDirectory(atPath: dirPath,
withIntermediateDirectories:true, withIntermediateDirectories: true,
attributes:nil) attributes: nil)
gifFolderPath = dirPath gifFolderPath = dirPath
} }
// Don't back up Giphy downloads. // Don't back up Giphy downloads.
OWSFileSystem.protectFileOrFolder(atPath:dirPath) OWSFileSystem.protectFileOrFolder(atPath: dirPath)
} catch let error as NSError { } catch let error as NSError {
owsFail("\(GiphyAsset.TAG) ensureTempFolder failed: \(dirPath), \(error)") owsFail("\(GiphyAsset.TAG) ensureTempFolder failed: \(dirPath), \(error)")
gifFolderPath = tempDirPath gifFolderPath = tempDirPath

@ -364,6 +364,7 @@ NS_ASSUME_NONNULL_BEGIN
[self ensureBackupExportState]; [self ensureBackupExportState];
} else { } else {
DDLogWarn(@"%@ obsolete job succeeded: %@", self.logTag, [backupJob class]);
return; return;
} }
@ -387,7 +388,7 @@ NS_ASSUME_NONNULL_BEGIN
[self ensureBackupExportState]; [self ensureBackupExportState];
} else { } else {
DDLogInfo(@"%@ stale backup job failed.", self.logTag); DDLogInfo(@"%@ obsolete backup job failed.", self.logTag);
return; return;
} }

@ -21,8 +21,8 @@ import CloudKit
@objc @objc
public class func saveTestFileToCloud(fileUrl: URL, public class func saveTestFileToCloud(fileUrl: URL,
success: @escaping (String) -> Swift.Void, success: @escaping (String) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
saveFileToCloud(fileUrl: fileUrl, saveFileToCloud(fileUrl: fileUrl,
recordName: NSUUID().uuidString, recordName: NSUUID().uuidString,
recordType: signalBackupRecordType, recordType: signalBackupRecordType,
@ -36,8 +36,8 @@ import CloudKit
// complete. // complete.
@objc @objc
public class func saveEphemeralDatabaseFileToCloud(fileUrl: URL, public class func saveEphemeralDatabaseFileToCloud(fileUrl: URL,
success: @escaping (String) -> Swift.Void, success: @escaping (String) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
saveFileToCloud(fileUrl: fileUrl, saveFileToCloud(fileUrl: fileUrl,
recordName: "ephemeralFile-\(NSUUID().uuidString)", recordName: "ephemeralFile-\(NSUUID().uuidString)",
recordType: signalBackupRecordType, recordType: signalBackupRecordType,
@ -50,9 +50,9 @@ import CloudKit
// backups can reuse the same record. // backups can reuse the same record.
@objc @objc
public class func savePersistentFileOnceToCloud(fileId: String, public class func savePersistentFileOnceToCloud(fileId: String,
fileUrlBlock: @escaping (Swift.Void) -> URL?, fileUrlBlock: @escaping (()) -> URL?,
success: @escaping (String) -> Swift.Void, success: @escaping (String) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
saveFileOnceToCloud(recordName: "persistentFile-\(fileId)", saveFileOnceToCloud(recordName: "persistentFile-\(fileId)",
recordType: signalBackupRecordType, recordType: signalBackupRecordType,
fileUrlBlock: fileUrlBlock, fileUrlBlock: fileUrlBlock,
@ -62,8 +62,8 @@ import CloudKit
@objc @objc
public class func upsertManifestFileToCloud(fileUrl: URL, public class func upsertManifestFileToCloud(fileUrl: URL,
success: @escaping (String) -> Swift.Void, success: @escaping (String) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
// We want to use a well-known record id and type for manifest files. // We want to use a well-known record id and type for manifest files.
upsertFileToCloud(fileUrl: fileUrl, upsertFileToCloud(fileUrl: fileUrl,
recordName: manifestRecordName, recordName: manifestRecordName,
@ -76,8 +76,8 @@ import CloudKit
public class func saveFileToCloud(fileUrl: URL, public class func saveFileToCloud(fileUrl: URL,
recordName: String, recordName: String,
recordType: String, recordType: String,
success: @escaping (String) -> Swift.Void, success: @escaping (String) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
let recordID = CKRecordID(recordName: recordName) let recordID = CKRecordID(recordName: recordName)
let record = CKRecord(recordType: recordType, recordID: recordID) let record = CKRecord(recordType: recordType, recordID: recordID)
let asset = CKAsset(fileURL: fileUrl) let asset = CKAsset(fileURL: fileUrl)
@ -90,8 +90,8 @@ import CloudKit
@objc @objc
public class func saveRecordToCloud(record: CKRecord, public class func saveRecordToCloud(record: CKRecord,
success: @escaping (String) -> Swift.Void, success: @escaping (String) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
let myContainer = CKContainer.default() let myContainer = CKContainer.default()
let privateDatabase = myContainer.privateCloudDatabase let privateDatabase = myContainer.privateCloudDatabase
@ -117,8 +117,8 @@ import CloudKit
@objc @objc
public class func deleteRecordFromCloud(recordName: String, public class func deleteRecordFromCloud(recordName: String,
success: @escaping (Swift.Void) -> Swift.Void, success: @escaping (()) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
let recordID = CKRecordID(recordName: recordName) let recordID = CKRecordID(recordName: recordName)
@ -146,8 +146,8 @@ import CloudKit
public class func upsertFileToCloud(fileUrl: URL, public class func upsertFileToCloud(fileUrl: URL,
recordName: String, recordName: String,
recordType: String, recordType: String,
success: @escaping (String) -> Swift.Void, success: @escaping (String) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
checkForFileInCloud(recordName: recordName, checkForFileInCloud(recordName: recordName,
success: { (record) in success: { (record) in
@ -178,9 +178,9 @@ import CloudKit
@objc @objc
public class func saveFileOnceToCloud(recordName: String, public class func saveFileOnceToCloud(recordName: String,
recordType: String, recordType: String,
fileUrlBlock: @escaping (Swift.Void) -> URL?, fileUrlBlock: @escaping (()) -> URL?,
success: @escaping (String) -> Swift.Void, success: @escaping (String) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
checkForFileInCloud(recordName: recordName, checkForFileInCloud(recordName: recordName,
success: { (record) in success: { (record) in
@ -208,8 +208,8 @@ import CloudKit
} }
private class func checkForFileInCloud(recordName: String, private class func checkForFileInCloud(recordName: String,
success: @escaping (CKRecord?) -> Swift.Void, success: @escaping (CKRecord?) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
let recordId = CKRecordID(recordName: recordName) let recordId = CKRecordID(recordName: recordName)
let fetchOperation = CKFetchRecordsOperation(recordIDs: [recordId ]) let fetchOperation = CKFetchRecordsOperation(recordIDs: [recordId ])
// Don't download the file; we're just using the fetch to check whether or // Don't download the file; we're just using the fetch to check whether or
@ -246,8 +246,8 @@ import CloudKit
} }
@objc @objc
public class func checkForManifestInCloud(success: @escaping (Bool) -> Swift.Void, public class func checkForManifestInCloud(success: @escaping (Bool) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
checkForFileInCloud(recordName: manifestRecordName, checkForFileInCloud(recordName: manifestRecordName,
success: { (record) in success: { (record) in
@ -257,8 +257,8 @@ import CloudKit
} }
@objc @objc
public class func fetchAllRecordNames(success: @escaping ([String]) -> Swift.Void, public class func fetchAllRecordNames(success: @escaping ([String]) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
let query = CKQuery(recordType: signalBackupRecordType, predicate: NSPredicate(value: true)) let query = CKQuery(recordType: signalBackupRecordType, predicate: NSPredicate(value: true))
// Fetch the first page of results for this query. // Fetch the first page of results for this query.
@ -272,8 +272,8 @@ import CloudKit
private class func fetchAllRecordNamesStep(query: CKQuery, private class func fetchAllRecordNamesStep(query: CKQuery,
previousRecordNames: [String], previousRecordNames: [String],
cursor: CKQueryCursor?, cursor: CKQueryCursor?,
success: @escaping ([String]) -> Swift.Void, success: @escaping ([String]) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
var allRecordNames = previousRecordNames var allRecordNames = previousRecordNames
@ -314,8 +314,8 @@ import CloudKit
@objc @objc
public class func downloadManifestFromCloud( public class func downloadManifestFromCloud(
success: @escaping (Data) -> Swift.Void, success: @escaping (Data) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
downloadDataFromCloud(recordName: manifestRecordName, downloadDataFromCloud(recordName: manifestRecordName,
success: success, success: success,
failure: failure) failure: failure)
@ -323,8 +323,8 @@ import CloudKit
@objc @objc
public class func downloadDataFromCloud(recordName: String, public class func downloadDataFromCloud(recordName: String,
success: @escaping (Data) -> Swift.Void, success: @escaping (Data) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
downloadFromCloud(recordName: recordName, downloadFromCloud(recordName: recordName,
success: { (asset) in success: { (asset) in
@ -346,8 +346,8 @@ import CloudKit
@objc @objc
public class func downloadFileFromCloud(recordName: String, public class func downloadFileFromCloud(recordName: String,
toFileUrl: URL, toFileUrl: URL,
success: @escaping (Swift.Void) -> Swift.Void, success: @escaping (()) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
downloadFromCloud(recordName: recordName, downloadFromCloud(recordName: recordName,
success: { (asset) in success: { (asset) in
@ -367,8 +367,8 @@ import CloudKit
} }
private class func downloadFromCloud(recordName: String, private class func downloadFromCloud(recordName: String,
success: @escaping (CKAsset) -> Swift.Void, success: @escaping (CKAsset) -> Void,
failure: @escaping (Error) -> Swift.Void) { failure: @escaping (Error) -> Void) {
let recordId = CKRecordID(recordName: recordName) let recordId = CKRecordID(recordName: recordName)
let fetchOperation = CKFetchRecordsOperation(recordIDs: [recordId ]) let fetchOperation = CKFetchRecordsOperation(recordIDs: [recordId ])
@ -400,7 +400,7 @@ import CloudKit
} }
@objc @objc
public class func checkCloudKitAccess(completion: @escaping (Bool) -> Swift.Void) { public class func checkCloudKitAccess(completion: @escaping (Bool) -> Void) {
CKContainer.default().accountStatus(completionHandler: { (accountStatus, error) in CKContainer.default().accountStatus(completionHandler: { (accountStatus, error) in
DispatchQueue.main.async { DispatchQueue.main.async {
switch accountStatus { switch accountStatus {

@ -389,7 +389,6 @@ typedef void (^DebugLogUploadFailure)(DebugLogUploader *uploader, NSError *error
[tempDirectory stringByAppendingPathComponent:[logsName stringByAppendingPathExtension:@"zip"]]; [tempDirectory stringByAppendingPathComponent:[logsName stringByAppendingPathExtension:@"zip"]];
NSString *zipDirPath = [tempDirectory stringByAppendingPathComponent:logsName]; NSString *zipDirPath = [tempDirectory stringByAppendingPathComponent:logsName];
[OWSFileSystem ensureDirectoryExists:zipDirPath]; [OWSFileSystem ensureDirectoryExists:zipDirPath];
[OWSFileSystem protectFileOrFolderAtPath:zipDirPath];
NSArray<NSString *> *logFilePaths = DebugLogger.sharedLogger.allLogFilePaths; NSArray<NSString *> *logFilePaths = DebugLogger.sharedLogger.allLogFilePaths;
if (logFilePaths.count < 1) { if (logFilePaths.count < 1) {

@ -42,7 +42,7 @@ class VerifyingTSAccountManager: FailingTSAccountManager {
success() success()
} }
override func registerForManualMessageFetching(success successBlock: @escaping () -> Swift.Void, failure failureBlock: @escaping (Error) -> Swift.Void) { override func registerForManualMessageFetching(success successBlock: @escaping () -> Void, failure failureBlock: @escaping (Error) -> Void) {
successBlock() successBlock()
} }
} }

@ -1124,8 +1124,6 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
profileAvatarsDirPath = OWSProfileManager.sharedDataProfileAvatarsDirPath; profileAvatarsDirPath = OWSProfileManager.sharedDataProfileAvatarsDirPath;
[OWSFileSystem ensureDirectoryExists:profileAvatarsDirPath]; [OWSFileSystem ensureDirectoryExists:profileAvatarsDirPath];
[OWSFileSystem protectFileOrFolderAtPath:profileAvatarsDirPath];
}); });
return profileAvatarsDirPath; return profileAvatarsDirPath;
} }

@ -39,7 +39,6 @@ const NSUInteger kMaxDebugLogFileSize = 1024 * 1024 * 3;
{ {
NSString *dirPath = [[OWSFileSystem cachesDirectoryPath] stringByAppendingPathComponent:@"Logs"]; NSString *dirPath = [[OWSFileSystem cachesDirectoryPath] stringByAppendingPathComponent:@"Logs"];
[OWSFileSystem ensureDirectoryExists:dirPath]; [OWSFileSystem ensureDirectoryExists:dirPath];
[OWSFileSystem protectFileOrFolderAtPath:dirPath];
return dirPath; return dirPath;
} }
@ -48,7 +47,6 @@ const NSUInteger kMaxDebugLogFileSize = 1024 * 1024 * 3;
NSString *dirPath = NSString *dirPath =
[[OWSFileSystem appSharedDataDirectoryPath] stringByAppendingPathComponent:@"ShareExtensionLogs"]; [[OWSFileSystem appSharedDataDirectoryPath] stringByAppendingPathComponent:@"ShareExtensionLogs"];
[OWSFileSystem ensureDirectoryExists:dirPath]; [OWSFileSystem ensureDirectoryExists:dirPath];
[OWSFileSystem protectFileOrFolderAtPath:dirPath];
return dirPath; return dirPath;
} }

@ -55,7 +55,7 @@ import Foundation
} }
@objc @objc
public class func showErrorAlert(message message: String) { public class func showErrorAlert(message: String) {
self.showAlert(title: CommonStrings.errorAlertTitle, message: message, buttonTitle: nil) self.showAlert(title: CommonStrings.errorAlertTitle, message: message, buttonTitle: nil)
} }

@ -210,8 +210,6 @@ NS_ASSUME_NONNULL_BEGIN
attachmentsFolder = TSAttachmentStream.sharedDataAttachmentsDirPath; attachmentsFolder = TSAttachmentStream.sharedDataAttachmentsDirPath;
[OWSFileSystem ensureDirectoryExists:attachmentsFolder]; [OWSFileSystem ensureDirectoryExists:attachmentsFolder];
[OWSFileSystem protectFileOrFolderAtPath:attachmentsFolder];
}); });
return attachmentsFolder; return attachmentsFolder;
} }

@ -21,8 +21,6 @@ typedef NSData *_Nullable (^BackupStorageKeySpecBlock)(void);
- (instancetype)initBackupStorageWithDatabaseDirPath:(NSString *)databaseDirPath - (instancetype)initBackupStorageWithDatabaseDirPath:(NSString *)databaseDirPath
keySpecBlock:(BackupStorageKeySpecBlock)keySpecBlock NS_DESIGNATED_INITIALIZER; keySpecBlock:(BackupStorageKeySpecBlock)keySpecBlock NS_DESIGNATED_INITIALIZER;
- (YapDatabaseConnection *)dbConnection;
- (void)runSyncRegistrations; - (void)runSyncRegistrations;
- (void)runAsyncRegistrationsWithCompletion:(void (^_Nonnull)(void))completion; - (void)runAsyncRegistrationsWithCompletion:(void (^_Nonnull)(void))completion;
- (BOOL)areAllRegistrationsComplete; - (BOOL)areAllRegistrationsComplete;

@ -210,7 +210,7 @@ NS_ASSUME_NONNULL_BEGIN
if (exists) { if (exists) {
OWSAssert(isDirectory); OWSAssert(isDirectory);
return YES; return [self protectFileOrFolderAtPath:dirPath];
} else { } else {
DDLogInfo(@"%@ Creating directory at: %@", self.logTag, dirPath); DDLogInfo(@"%@ Creating directory at: %@", self.logTag, dirPath);
@ -223,7 +223,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSFail(@"%@ Failed to create directory: %@, error: %@", self.logTag, dirPath, error); OWSFail(@"%@ Failed to create directory: %@, error: %@", self.logTag, dirPath, error);
return NO; return NO;
} }
return YES; return [self protectFileOrFolderAtPath:dirPath];
} }
} }

Loading…
Cancel
Save