session-ios/Signal/src/view controllers/InCallViewController.m

257 lines
8.6 KiB
Objective-C

#import "AppAudioManager.h"
#import "CallFailedServerMessage.h"
#import "InCallViewController.h"
#import "LocalizableText.h"
#import "RecentCallManager.h"
#define BUTTON_BORDER_WIDTH 1.0f
#define CONTACT_IMAGE_BORDER_WIDTH 2.0f
#define RINGING_ROTATION_DURATION 0.375f
#define VIBRATE_TIMER_DURATION 1.6
#define CONNECTING_FLASH_DURATION 0.5f
#define END_CALL_CLEANUP_DELAY (int)(3.1f * NSEC_PER_SEC)
@interface InCallViewController () {
CallAudioManager *_callAudioManager;
NSTimer *_connectingFlashTimer;
NSTimer *_ringingAnimationTimer;
}
@property NSTimer *vibrateTimer;
@end
@implementation InCallViewController
- (void)configureWithLatestCall:(CallState *)callState {
_potentiallyKnownContact = callState.potentiallySpecifiedContact;
_callState = callState;
_callPushState = PushNotSetState;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self showCallState];
[self setPotentiallyKnownContact:_potentiallyKnownContact];
[self localizeButtons];
[self linkActions];
[[[[Environment getCurrent] contactsManager] getObservableContacts] watchLatestValue:^(NSArray *latestContacts) {
[self setPotentiallyKnownContact:[[[Environment getCurrent] contactsManager]
latestContactForPhoneNumber:_callState.remoteNumber]];
}
onThread:[NSThread mainThread]
untilCancelled:nil];
_callStatusLabel.lineBreakMode = NSLineBreakByWordWrapping | NSLineBreakByTruncatingTail;
}
- (void)linkActions {
[_muteButton addTarget:self action:@selector(muteButtonTapped) forControlEvents:UIControlEventTouchUpInside];
[_speakerButton addTarget:self action:@selector(speakerButtonTapped) forControlEvents:UIControlEventTouchUpInside];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[UIDevice.currentDevice setProximityMonitoringEnabled:YES];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self stopRingingAnimation];
[self stopConnectingFlashAnimation];
[AppAudioManager.sharedInstance cancelAllAudio];
[UIDevice.currentDevice setProximityMonitoringEnabled:NO];
}
- (void)showCallState {
[self clearDetails];
[self populateImmediateDetails];
[self handleIncomingDetails];
}
- (void)startRingingAnimation {
[self stopConnectingFlashAnimation];
if (!_incomingCallButtonsView.hidden) {
_vibrateTimer = [NSTimer scheduledTimerWithTimeInterval:VIBRATE_TIMER_DURATION
target:self
selector:@selector(vibrate)
userInfo:nil
repeats:YES];
}
[_ringingAnimationTimer fire];
}
- (void)vibrate {
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
- (void)stopRingingAnimation {
if (_ringingAnimationTimer) {
[_ringingAnimationTimer invalidate];
}
if (_vibrateTimer) {
[_vibrateTimer invalidate];
}
}
- (void)stopConnectingFlashAnimation {
if (_connectingFlashTimer) {
[_connectingFlashTimer invalidate];
}
}
- (void)showConnectingError {
[self stopRingingAnimation];
[self stopConnectingFlashAnimation];
}
- (void)localizeButtons {
[_endButton setTitle:NSLocalizedString(@"END_CALL_BUTTON_TITLE", @"") forState:UIControlStateNormal];
[_answerButton setTitle:NSLocalizedString(@"ANSWER_CALL_BUTTON_TITLE", @"") forState:UIControlStateNormal];
[_rejectButton setTitle:NSLocalizedString(@"REJECT_CALL_BUTTON_TITLE", @"") forState:UIControlStateNormal];
}
- (void)setPotentiallyKnownContact:(Contact *)potentiallyKnownContact {
_potentiallyKnownContact = potentiallyKnownContact;
if (_potentiallyKnownContact) {
if (_potentiallyKnownContact.image) {
[UIUtil applyRoundedBorderToImageView:_contactImageView];
}
_nameLabel.text = _potentiallyKnownContact.fullName;
} else {
_nameLabel.text = _callState.remoteNumber.toE164;
}
}
- (void)clearDetails {
_callStatusLabel.text = @"";
_nameLabel.text = @"";
_authenicationStringLabel.text = @"";
_explainAuthenticationStringLabel.text = @"";
_contactImageView.image = nil;
_safeWordsView.hidden = YES;
_muteButton.hidden = YES;
_speakerButton.hidden = YES;
[self displayAcceptRejectButtons:NO];
}
- (void)populateImmediateDetails {
if (_potentiallyKnownContact) {
_nameLabel.text = _potentiallyKnownContact.fullName;
if (_potentiallyKnownContact.image) {
_contactImageView.image = _potentiallyKnownContact.image;
}
}
}
- (void)handleIncomingDetails {
[_callState.futureShortAuthenticationString thenDo:^(NSString *sas) {
_authenicationStringLabel.textColor = [UIColor ows_materialBlueColor];
_safeWordsView.hidden = NO;
_muteButton.hidden = NO;
_speakerButton.hidden = NO;
_authenicationStringLabel.text = sas;
}];
[[_callState observableProgress] watchLatestValue:^(CallProgress *latestProgress) {
[self onCallProgressed:latestProgress];
}
onThread:NSThread.mainThread
untilCancelled:nil];
}
- (void)onCallProgressed:(CallProgress *)latestProgress {
BOOL showAcceptRejectButtons = !_callState.initiatedLocally && [latestProgress type] <= CallProgressType_Ringing;
[self displayAcceptRejectButtons:showAcceptRejectButtons];
[AppAudioManager.sharedInstance respondToProgressChange:[latestProgress type]
forLocallyInitiatedCall:_callState.initiatedLocally];
if ([latestProgress type] == CallProgressType_Ringing) {
[self startRingingAnimation];
}
if ([latestProgress type] == CallProgressType_Terminated) {
[_callState.futureTermination thenDo:^(CallTermination *termination) {
[self onCallEnded:termination];
[AppAudioManager.sharedInstance respondToTerminationType:[termination type]];
}];
} else {
_callStatusLabel.text = latestProgress.localizedDescriptionForUser;
}
}
- (void)onCallEnded:(CallTermination *)termination {
[self updateViewForTermination:termination];
[Environment.phoneManager hangupOrDenyCall];
[self dismissViewWithOptionalDelay:[termination type] != CallTerminationType_ReplacedByNext];
}
- (void)endCallTapped {
[Environment.phoneManager hangupOrDenyCall];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)muteButtonTapped {
[_muteButton setSelected:[Environment.phoneManager toggleMute]];
}
- (void)speakerButtonTapped {
[_speakerButton setSelected:[AppAudioManager.sharedInstance toggleSpeakerPhone]];
}
- (void)answerButtonTapped {
[self displayAcceptRejectButtons:NO];
[Environment.phoneManager answerCall];
}
- (void)rejectButtonTapped {
[self displayAcceptRejectButtons:NO];
[Environment.phoneManager hangupOrDenyCall];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)updateViewForTermination:(CallTermination *)termination {
NSString *message = termination.localizedDescriptionForUser;
if ([termination type] == CallTerminationType_ServerMessage) {
CallFailedServerMessage *serverMessage = [termination messageInfo];
message = [message stringByAppendingString:[serverMessage text]];
}
_callStatusLabel.textColor = [UIColor ows_redColor];
[self showConnectingError];
_callStatusLabel.text = message;
}
- (void)dismissViewWithOptionalDelay:(BOOL)useDelay {
if (useDelay && UIApplicationStateActive == [UIApplication.sharedApplication applicationState]) {
[self dismissViewControllerAfterDelay:END_CALL_CLEANUP_DELAY];
} else {
[self dismissViewControllerAnimated:NO completion:nil];
}
}
- (void)dismissViewControllerAfterDelay:(int)delay {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay), dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:nil];
});
}
- (void)displayAcceptRejectButtons:(BOOL)enable {
_incomingCallButtonsView.hidden = !enable;
_activeCallButtonsView.hidden = enable;
if (_vibrateTimer && enable == false) {
[_vibrateTimer invalidate];
}
}
@end