Signal-iOS/SignalMessaging/contacts/ViewControllerUtils.m
Michael Kirk c646f76335 Garther audio concerns, clean up session when done
- sync speakerphone state manipulated from system call screen
  - Revert audio session after call failure, ensures media plays out of
    speaker after placing a failing call.
  - Replace notification with delegate pattern since we're already using
    delegate pattern here.
- Fixes voiceover accessibility after voice memo
- Avoid audio blip after pressing hangup
- Rename CallAudioSession -> OWSAudioSession
  Going to start using it for other non-call things since we want to
  gather all our audio session concerns.
- Resume background audio when done playing video
  - Extract OWSVideoPlayer which ensures audio is in proper state before
    playback
  - Move recording session logic to shared OWSAudioSession
  - Deactivate audio session when complete

// FREEBIE
2018-02-06 18:45:51 -08:00

105 lines
4.9 KiB
Objective-C

//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "ViewControllerUtils.h"
#import "HomeViewController.h"
#import "NSString+OWS.h"
#import "PhoneNumber.h"
#import <AVFoundation/AVFoundation.h>
#import <SignalMessaging/Environment.h>
#import <SignalServiceKit/PhoneNumberUtil.h>
NS_ASSUME_NONNULL_BEGIN
#pragma mark -
@implementation ViewControllerUtils
+ (void)phoneNumberTextField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)insertionText
countryCode:(NSString *)countryCode
{
// Phone numbers takes many forms.
//
// * We only want to let the user enter decimal digits.
// * The user shouldn't have to enter hyphen, parentheses or whitespace;
// the phone number should be formatted automatically.
// * The user should be able to copy and paste freely.
// * Invalid input should be simply ignored.
//
// We accomplish this by being permissive and trying to "take as much of the user
// input as possible".
//
// * Always accept deletes.
// * Ignore invalid input.
// * Take partial input if possible.
NSString *oldText = textField.text;
// Construct the new contents of the text field by:
// 1. Determining the "left" substring: the contents of the old text _before_ the deletion range.
// Filtering will remove non-decimal digit characters like hyphen "-".
NSString *left = [oldText substringToIndex:range.location].digitsOnly;
// 2. Determining the "right" substring: the contents of the old text _after_ the deletion range.
NSString *right = [oldText substringFromIndex:range.location + range.length].digitsOnly;
// 3. Determining the "center" substring: the contents of the new insertion text.
NSString *center = insertionText.digitsOnly;
// 4. Construct the "raw" new text by concatenating left, center and right.
NSString *textAfterChange = [[left stringByAppendingString:center] stringByAppendingString:right];
// 4a. Ensure we don't exceed the maximum length for a e164 phone number,
// 15 digits, per: https://en.wikipedia.org/wiki/E.164
//
// NOTE: The actual limit is 18, not 15, because of certain invalid phone numbers in Germany.
// https://github.com/googlei18n/libphonenumber/blob/master/FALSEHOODS.md
const int kMaxPhoneNumberLength = 18;
if (textAfterChange.length > kMaxPhoneNumberLength) {
textAfterChange = [textAfterChange substringToIndex:kMaxPhoneNumberLength];
}
// 5. Construct the "formatted" new text by inserting a hyphen if necessary.
// reformat the phone number, trying to keep the cursor beside the inserted or deleted digit
bool isJustDeletion = insertionText.length == 0;
NSUInteger cursorPositionAfterChange = MIN(left.length + center.length, textAfterChange.length);
NSString *textAfterReformat =
[PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:textAfterChange
withSpecifiedCountryCodeString:countryCode];
NSUInteger cursorPositionAfterReformat = [PhoneNumberUtil translateCursorPosition:cursorPositionAfterChange
from:textAfterChange
to:textAfterReformat
stickingRightward:isJustDeletion];
textField.text = textAfterReformat;
UITextPosition *pos =
[textField positionFromPosition:textField.beginningOfDocument offset:(NSInteger)cursorPositionAfterReformat];
[textField setSelectedTextRange:[textField textRangeFromPosition:pos toPosition:pos]];
}
+ (NSString *)examplePhoneNumberForCountryCode:(NSString *)countryCode callingCode:(NSString *)callingCode
{
OWSAssert(countryCode.length > 0);
OWSAssert(callingCode.length > 0);
NSString *examplePhoneNumber = [PhoneNumberUtil examplePhoneNumberForCountryCode:countryCode];
OWSAssert(!examplePhoneNumber || [examplePhoneNumber hasPrefix:callingCode]);
if (examplePhoneNumber && [examplePhoneNumber hasPrefix:callingCode]) {
NSString *formattedPhoneNumber =
[PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:examplePhoneNumber
withSpecifiedCountryCodeString:countryCode];
if (formattedPhoneNumber.length > 0) {
examplePhoneNumber = formattedPhoneNumber;
}
return [NSString
stringWithFormat:
NSLocalizedString(@"PHONE_NUMBER_EXAMPLE_FORMAT",
@"A format for a label showing an example phone number. Embeds {{the example phone number}}."),
[examplePhoneNumber substringFromIndex:callingCode.length]];
} else {
return @"";
}
}
@end
NS_ASSUME_NONNULL_END