Merge branch 'hotfix/2.15.2'

pull/1/head
Matthew Chen 8 years ago
commit 43b3abe321

@ -38,7 +38,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.15.1</string> <string>2.15.2</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>
@ -55,7 +55,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2.15.1.0</string> <string>2.15.2.1</string>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>LOGS_EMAIL</key> <key>LOGS_EMAIL</key>

@ -728,6 +728,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
keyboardOnViewAppearing:(BOOL)keyboardOnViewAppearing keyboardOnViewAppearing:(BOOL)keyboardOnViewAppearing
callOnViewAppearing:(BOOL)callOnViewAppearing callOnViewAppearing:(BOOL)callOnViewAppearing
{ {
// TODO: Do this synchronously if we're already on the main thread.
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
MessagesViewController *mvc = [[MessagesViewController alloc] initWithNibName:@"MessagesViewController" MessagesViewController *mvc = [[MessagesViewController alloc] initWithNibName:@"MessagesViewController"
bundle:nil]; bundle:nil];
@ -736,11 +737,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
callOnViewAppearing:callOnViewAppearing]; callOnViewAppearing:callOnViewAppearing];
self.lastThread = thread; self.lastThread = thread;
if (self.presentedViewController) { [self pushTopLevelViewController:mvc animateDismissal:YES animatePresentation:YES];
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
[self.navigationController popToRootViewControllerAnimated:YES];
[self.navigationController pushViewController:mvc animated:YES];
}); });
} }
@ -799,6 +796,10 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
// Perform the first step. // Perform the first step.
if (self.presentedViewController) { if (self.presentedViewController) {
if ([self.presentedViewController isKindOfClass:[CallViewController class]]) {
OWSProdInfo([OWSAnalyticsEvents errorCouldNotPresentViewDueToCall]);
return;
}
[self.presentedViewController dismissViewControllerAnimated:animateDismissal completion:dismissNavigationBlock]; [self.presentedViewController dismissViewControllerAnimated:animateDismissal completion:dismissNavigationBlock];
} else { } else {
dismissNavigationBlock(); dismissNavigationBlock();

@ -144,8 +144,10 @@ protocol CallServiceObserver: class {
if let oldValue = oldValue { if let oldValue = oldValue {
DeviceSleepManager.sharedInstance.removeBlock(blockObject: oldValue) DeviceSleepManager.sharedInstance.removeBlock(blockObject: oldValue)
} }
stopAnyCallTimer()
if let call = call { if let call = call {
DeviceSleepManager.sharedInstance.addBlock(blockObject: call) DeviceSleepManager.sharedInstance.addBlock(blockObject: call)
self.startCallTimer()
} }
} }
@ -894,7 +896,7 @@ protocol CallServiceObserver: class {
* For incoming call, when the local user has chosen to accept the call. * For incoming call, when the local user has chosen to accept the call.
*/ */
func handleConnectedCall(_ call: SignalCall) { func handleConnectedCall(_ call: SignalCall) {
Logger.debug("\(TAG) in \(#function)") Logger.info("\(TAG) in \(#function)")
AssertIsOnMainThread() AssertIsOnMainThread()
guard let peerConnectionClient = self.peerConnectionClient else { guard let peerConnectionClient = self.peerConnectionClient else {
@ -1567,6 +1569,60 @@ protocol CallServiceObserver: class {
remoteVideoTrack:remoteVideoTrack) remoteVideoTrack:remoteVideoTrack)
} }
} }
// MARK: CallViewController Timer
var activeCallTimer: Timer?
func startCallTimer() {
AssertIsOnMainThread()
if self.activeCallTimer != nil {
owsFail("\(TAG) activeCallTimer should only be set once per call")
self.activeCallTimer!.invalidate()
self.activeCallTimer = nil
}
self.activeCallTimer = WeakTimer.scheduledTimer(timeInterval: 1, target: self, userInfo: nil, repeats: true) { [weak self] timer in
guard let strongSelf = self else {
return
}
guard let call = strongSelf.call else {
owsFail("\(strongSelf.TAG) call has since ended. Timer should have been invalidated.")
timer.invalidate()
return
}
strongSelf.ensureCallScreenPresented(call: call)
}
}
func ensureCallScreenPresented(call: SignalCall) {
guard let connectedDate = call.connectedDate else {
// Ignore; call hasn't connected yet.
return
}
let kMaxViewPresentationDelay = 2.5
guard fabs(connectedDate.timeIntervalSinceNow) > kMaxViewPresentationDelay else {
// Ignore; call connected recently.
return
}
guard nil != UIApplication.shared.frontmostViewController as? CallViewController else {
OWSProdError(OWSAnalyticsEvents.callServiceCallViewCouldNotPresent(), file:#file, function:#function, line:#line)
owsFail("\(TAG) in \(#function) Call terminated due to call view presentation delay.")
self.terminateCall()
return
}
}
func stopAnyCallTimer() {
AssertIsOnMainThread()
self.activeCallTimer?.invalidate()
self.activeCallTimer = nil
}
} }
fileprivate extension MessageSender { fileprivate extension MessageSender {

@ -31,7 +31,7 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
Logger.debug("\(self.TAG) handleOutgoingCall succeeded") Logger.debug("\(self.TAG) handleOutgoingCall succeeded")
}.catch { error in }.catch { error in
Logger.error("\(self.TAG) handleOutgoingCall failed with error: \(error)") Logger.error("\(self.TAG) handleOutgoingCall failed with error: \(error)")
} }.retainUntilComplete()
return call return call
} }

@ -67,7 +67,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
func startOutgoingCall(handle: String) -> SignalCall { func startOutgoingCall(handle: String) -> SignalCall {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
let call = SignalCall.outgoingCall(localId: UUID(), remotePhoneNumber: handle) let call = SignalCall.outgoingCall(localId: UUID(), remotePhoneNumber: handle)
@ -82,7 +82,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
// Called from CallService after call has ended to clean up any remaining CallKit call state. // Called from CallService after call has ended to clean up any remaining CallKit call state.
func failCall(_ call: SignalCall, error: CallError) { func failCall(_ call: SignalCall, error: CallError) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
switch error { switch error {
case .timeout(description: _): case .timeout(description: _):
@ -96,7 +96,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
func reportIncomingCall(_ call: SignalCall, callerName: String) { func reportIncomingCall(_ call: SignalCall, callerName: String) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
// Construct a CXCallUpdate describing the incoming call, including the caller. // Construct a CXCallUpdate describing the incoming call, including the caller.
let update = CXCallUpdate() let update = CXCallUpdate()
@ -130,14 +130,14 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
func answerCall(localId: UUID) { func answerCall(localId: UUID) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
owsFail("\(self.TAG) \(#function) CallKit should answer calls via system call screen, not via notifications.") owsFail("\(self.TAG) \(#function) CallKit should answer calls via system call screen, not via notifications.")
} }
func answerCall(_ call: SignalCall) { func answerCall(_ call: SignalCall) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
callManager.answer(call: call) callManager.answer(call: call)
} }
@ -150,14 +150,14 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
func declineCall(_ call: SignalCall) { func declineCall(_ call: SignalCall) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
callManager.localHangup(call: call) callManager.localHangup(call: call)
} }
func recipientAcceptedCall(_ call: SignalCall) { func recipientAcceptedCall(_ call: SignalCall) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
self.provider.reportOutgoingCall(with: call.localId, connectedAt: nil) self.provider.reportOutgoingCall(with: call.localId, connectedAt: nil)
@ -169,28 +169,28 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
func localHangupCall(_ call: SignalCall) { func localHangupCall(_ call: SignalCall) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
callManager.localHangup(call: call) callManager.localHangup(call: call)
} }
func remoteDidHangupCall(_ call: SignalCall) { func remoteDidHangupCall(_ call: SignalCall) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
provider.reportCall(with: call.localId, endedAt: nil, reason: CXCallEndedReason.remoteEnded) provider.reportCall(with: call.localId, endedAt: nil, reason: CXCallEndedReason.remoteEnded)
} }
func remoteBusy(_ call: SignalCall) { func remoteBusy(_ call: SignalCall) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
provider.reportCall(with: call.localId, endedAt: nil, reason: CXCallEndedReason.unanswered) provider.reportCall(with: call.localId, endedAt: nil, reason: CXCallEndedReason.unanswered)
} }
func setIsMuted(call: SignalCall, isMuted: Bool) { func setIsMuted(call: SignalCall, isMuted: Bool) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
callManager.setIsMuted(call: call, isMuted: isMuted) callManager.setIsMuted(call: call, isMuted: isMuted)
} }
@ -212,7 +212,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
func providerDidReset(_ provider: CXProvider) { func providerDidReset(_ provider: CXProvider) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)") Logger.info("\(self.TAG) \(#function)")
// Stop any in-progress WebRTC related audio. // Stop any in-progress WebRTC related audio.
PeerConnectionClient.stopAudioSession() PeerConnectionClient.stopAudioSession()
@ -228,7 +228,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
func provider(_ provider: CXProvider, perform action: CXStartCallAction) { func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(TAG) in \(#function) CXStartCallAction") Logger.info("\(TAG) in \(#function) CXStartCallAction")
guard let call = callManager.callWithLocalId(action.callUUID) else { guard let call = callManager.callWithLocalId(action.callUUID) else {
Logger.error("\(TAG) unable to find call in \(#function)") Logger.error("\(TAG) unable to find call in \(#function)")
@ -256,7 +256,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) { func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(TAG) Received \(#function) CXAnswerCallAction") Logger.info("\(TAG) Received \(#function) CXAnswerCallAction")
// Retrieve the instance corresponding to the action's call UUID // Retrieve the instance corresponding to the action's call UUID
guard let call = callManager.callWithLocalId(action.callUUID) else { guard let call = callManager.callWithLocalId(action.callUUID) else {
action.fail() action.fail()
@ -271,7 +271,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
public func provider(_ provider: CXProvider, perform action: CXEndCallAction) { public func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(TAG) Received \(#function) CXEndCallAction") Logger.info("\(TAG) Received \(#function) CXEndCallAction")
guard let call = callManager.callWithLocalId(action.callUUID) else { guard let call = callManager.callWithLocalId(action.callUUID) else {
Logger.error("\(self.TAG) in \(#function) trying to end unknown call with localId: \(action.callUUID)") Logger.error("\(self.TAG) in \(#function) trying to end unknown call with localId: \(action.callUUID)")
action.fail() action.fail()
@ -290,7 +290,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
public func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) { public func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(TAG) Received \(#function) CXSetHeldCallAction") Logger.info("\(TAG) Received \(#function) CXSetHeldCallAction")
guard let call = callManager.callWithLocalId(action.callUUID) else { guard let call = callManager.callWithLocalId(action.callUUID) else {
action.fail() action.fail()
return return
@ -316,7 +316,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
public func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) { public func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(TAG) Received \(#function) CXSetMutedCallAction") Logger.info("\(TAG) Received \(#function) CXSetMutedCallAction")
guard callManager.callWithLocalId(action.callUUID) != nil else { guard callManager.callWithLocalId(action.callUUID) != nil else {
Logger.error("\(TAG) Failing CXSetMutedCallAction for unknown call: \(action.callUUID)") Logger.error("\(TAG) Failing CXSetMutedCallAction for unknown call: \(action.callUUID)")
action.fail() action.fail()
@ -342,7 +342,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) { func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(TAG) Timed out \(#function) while performing \(action)") owsFail("\(TAG) Timed out \(#function) while performing \(action)")
// React to the action timeout if necessary, such as showing an error UI. // React to the action timeout if necessary, such as showing an error UI.
} }

@ -34,7 +34,7 @@ extension CallUIAdaptee {
internal func showCall(_ call: SignalCall) { internal func showCall(_ call: SignalCall) {
AssertIsOnMainThread() AssertIsOnMainThread()
let callViewController = CallViewController(call:call) let callViewController = CallViewController(call: call)
callViewController.modalTransitionStyle = .crossDissolve callViewController.modalTransitionStyle = .crossDissolve
guard let presentingViewController = Environment.getCurrent().signalsViewController else { guard let presentingViewController = Environment.getCurrent().signalsViewController else {

@ -16,6 +16,9 @@ NS_ASSUME_NONNULL_BEGIN
@interface TSThread : TSYapDatabaseObject @interface TSThread : TSYapDatabaseObject
// YES IFF this thread has ever had a message.
@property (nonatomic) BOOL hasEverHadMessage;
/** /**
* Whether the object is a group thread or not. * Whether the object is a group thread or not.
* *

@ -321,6 +321,8 @@ NS_ASSUME_NONNULL_BEGIN
return; return;
} }
self.hasEverHadMessage = YES;
NSDate *lastMessageDate = [lastMessage dateForSorting]; NSDate *lastMessageDate = [lastMessage dateForSorting];
if (!_lastMessageDate || [lastMessageDate timeIntervalSinceDate:self.lastMessageDate] > 0) { if (!_lastMessageDate || [lastMessageDate timeIntervalSinceDate:self.lastMessageDate] > 0) {
_lastMessageDate = lastMessageDate; _lastMessageDate = lastMessageDate;

@ -224,11 +224,17 @@ NSString *const TSSecondaryDevicesDatabaseViewExtensionName = @"TSSecondaryDevic
TSThread *thread = (TSThread *)object; TSThread *thread = (TSThread *)object;
YapDatabaseViewTransaction *viewTransaction = [transaction ext:TSMessageDatabaseViewExtensionName]; if (thread.isGroupThread) {
OWSAssert(viewTransaction); // Do nothing; we never hide group threads.
NSUInteger threadMessageCount = [viewTransaction numberOfItemsInGroup:thread.uniqueId]; } else if (thread.hasEverHadMessage) {
if (threadMessageCount < 1) { // Do nothing; we never hide threads that have ever had a message.
return nil; } else {
YapDatabaseViewTransaction *viewTransaction = [transaction ext:TSMessageDatabaseViewExtensionName];
OWSAssert(viewTransaction);
NSUInteger threadMessageCount = [viewTransaction numberOfItemsInGroup:thread.uniqueId];
if (threadMessageCount < 1) {
return nil;
}
} }
if (thread.archivalDate) { if (thread.archivalDate) {
@ -248,7 +254,7 @@ NSString *const TSSecondaryDevicesDatabaseViewExtensionName = @"TSSecondaryDevic
[[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[TSThread collection]]]; [[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[TSThread collection]]];
YapDatabaseView *databaseView = YapDatabaseView *databaseView =
[[YapDatabaseView alloc] initWithGrouping:viewGrouping sorting:viewSorting versionTag:@"2" options:options]; [[YapDatabaseView alloc] initWithGrouping:viewGrouping sorting:viewSorting versionTag:@"3" options:options];
[[TSStorageManager sharedManager].database registerExtension:databaseView [[TSStorageManager sharedManager].database registerExtension:databaseView
withName:TSThreadDatabaseViewExtensionName]; withName:TSThreadDatabaseViewExtensionName];

@ -36,6 +36,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSString *)callServiceCallUnexpectedlyIdle; + (NSString *)callServiceCallUnexpectedlyIdle;
+ (NSString *)callServiceCallViewCouldNotPresent;
+ (NSString *)callServiceCouldNotCreatePeerConnectionClientPromise; + (NSString *)callServiceCouldNotCreatePeerConnectionClientPromise;
+ (NSString *)callServiceCouldNotCreateReadyToSendIceUpdatesPromise; + (NSString *)callServiceCouldNotCreateReadyToSendIceUpdatesPromise;
@ -72,6 +74,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSString *)errorAttachmentRequestFailed; + (NSString *)errorAttachmentRequestFailed;
+ (NSString *)errorCouldNotPresentViewDueToCall;
+ (NSString *)errorEnableVideoCallingRequestFailed; + (NSString *)errorEnableVideoCallingRequestFailed;
+ (NSString *)errorGetDevicesFailed; + (NSString *)errorGetDevicesFailed;

@ -72,6 +72,11 @@ NS_ASSUME_NONNULL_BEGIN
return @"call_service_call_unexpectedly_idle"; return @"call_service_call_unexpectedly_idle";
} }
+ (NSString *)callServiceCallViewCouldNotPresent
{
return @"call_service_call_view_could_not_present";
}
+ (NSString *)callServiceCouldNotCreatePeerConnectionClientPromise + (NSString *)callServiceCouldNotCreatePeerConnectionClientPromise
{ {
return @"call_service_could_not_create_peer_connection_client_promise"; return @"call_service_could_not_create_peer_connection_client_promise";
@ -162,6 +167,11 @@ NS_ASSUME_NONNULL_BEGIN
return @"error_attachment_request_failed"; return @"error_attachment_request_failed";
} }
+ (NSString *)errorCouldNotPresentViewDueToCall
{
return @"error_could_not_present_view_due_to_call";
}
+ (NSString *)errorEnableVideoCallingRequestFailed + (NSString *)errorEnableVideoCallingRequestFailed
{ {
return @"error_enable_video_calling_request_failed"; return @"error_enable_video_calling_request_failed";

Loading…
Cancel
Save