mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-05-13 03:09:58 +02:00
Merge pull request #1477 from morozkin/incoming_call_screen
Add screen for incoming calls
This commit is contained in:
@@ -76,6 +76,8 @@
|
||||
32D392191EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 32D392171EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.xib */; };
|
||||
32FD0A3D1EB0CD9B0072B066 /* BugReportViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 32FD0A3B1EB0CD9B0072B066 /* BugReportViewController.m */; };
|
||||
32FD0A3E1EB0CD9B0072B066 /* BugReportViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 32FD0A3C1EB0CD9B0072B066 /* BugReportViewController.xib */; };
|
||||
92324BE31F4F66D3009DE194 /* IncomingCallView.m in Sources */ = {isa = PBXBuildFile; fileRef = 92324BE21F4F66D3009DE194 /* IncomingCallView.m */; };
|
||||
92324BE61F4F6A60009DE194 /* CircleButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 92324BE51F4F6A60009DE194 /* CircleButton.m */; };
|
||||
A27ECCE3FC4971745D2CB78D /* libPods-RiotShareExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7246451C668D6782166E22EC /* libPods-RiotShareExtension.a */; };
|
||||
F0131DE51F2200D600CBF707 /* RiotSplitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F0131DE41F2200D600CBF707 /* RiotSplitViewController.m */; };
|
||||
F02C1A861E8EB04C0045A404 /* PeopleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F02C1A841E8EB04C0045A404 /* PeopleViewController.m */; };
|
||||
@@ -646,6 +648,10 @@
|
||||
7246451C668D6782166E22EC /* libPods-RiotShareExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RiotShareExtension.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
765F5104DB3EC39713DEB3A4 /* Pods-RiotShareExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotShareExtension.release.xcconfig"; path = "Pods/Target Support Files/Pods-RiotShareExtension/Pods-RiotShareExtension.release.xcconfig"; sourceTree = "<group>"; };
|
||||
839BB91240D350D5607D55BA /* Pods-Riot.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Riot.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Riot/Pods-Riot.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
92324BE11F4F66D3009DE194 /* IncomingCallView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IncomingCallView.h; sourceTree = "<group>"; };
|
||||
92324BE21F4F66D3009DE194 /* IncomingCallView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IncomingCallView.m; sourceTree = "<group>"; };
|
||||
92324BE41F4F6A60009DE194 /* CircleButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CircleButton.h; sourceTree = "<group>"; };
|
||||
92324BE51F4F6A60009DE194 /* CircleButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CircleButton.m; sourceTree = "<group>"; };
|
||||
C195C53961EA28E6900AEB68 /* Pods-Riot.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Riot.release.xcconfig"; path = "Pods/Target Support Files/Pods-Riot/Pods-Riot.release.xcconfig"; sourceTree = "<group>"; };
|
||||
F0131DE31F2200D600CBF707 /* RiotSplitViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RiotSplitViewController.h; sourceTree = "<group>"; };
|
||||
F0131DE41F2200D600CBF707 /* RiotSplitViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RiotSplitViewController.m; sourceTree = "<group>"; };
|
||||
@@ -1412,6 +1418,17 @@
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
92324BE01F4F668F009DE194 /* Calls */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
92324BE11F4F66D3009DE194 /* IncomingCallView.h */,
|
||||
92324BE21F4F66D3009DE194 /* IncomingCallView.m */,
|
||||
92324BE41F4F6A60009DE194 /* CircleButton.h */,
|
||||
92324BE51F4F6A60009DE194 /* CircleButton.m */,
|
||||
);
|
||||
path = Calls;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F083BB021E7005FD00A9B29C /* RiotTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1920,6 +1937,7 @@
|
||||
F083BC571E7009EC00A9B29C /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
92324BE01F4F668F009DE194 /* Calls */,
|
||||
F0B4CBAD1F4215E3008E99C5 /* Event */,
|
||||
F083BC581E7009EC00A9B29C /* Authentication */,
|
||||
F083BC5F1E7009EC00A9B29C /* Contact */,
|
||||
@@ -2993,6 +3011,7 @@
|
||||
F083BE9C1E7009ED00A9B29C /* TableViewCellWithCheckBoxAndLabel.m in Sources */,
|
||||
32471CE11F13AC1500BDF50A /* RoomMembershipExpandedWithPaginationTitleBubbleCell.m in Sources */,
|
||||
F083BDFE1E7009ED00A9B29C /* RecentCellData.m in Sources */,
|
||||
92324BE61F4F6A60009DE194 /* CircleButton.m in Sources */,
|
||||
F083BE3A1E7009ED00A9B29C /* RoomIncomingEncryptedAttachmentBubbleCell.m in Sources */,
|
||||
3205ED841E97725E003D65FA /* DirectoryServerTableViewCell.m in Sources */,
|
||||
F083BEA21E7009ED00A9B29C /* TableViewCellWithPhoneNumberTextField.m in Sources */,
|
||||
@@ -3026,6 +3045,7 @@
|
||||
F083BE481E7009ED00A9B29C /* RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */,
|
||||
F06CDD691EF01E3900870B75 /* RoomEmptyBubbleCell.m in Sources */,
|
||||
F083BE041E7009ED00A9B29C /* Tools.m in Sources */,
|
||||
92324BE31F4F66D3009DE194 /* IncomingCallView.m in Sources */,
|
||||
F083BE6A1E7009ED00A9B29C /* RoomOutgoingAttachmentBubbleCell.m in Sources */,
|
||||
F083BDEF1E7009ED00A9B29C /* UINavigationController+Riot.m in Sources */,
|
||||
F083BE761E7009ED00A9B29C /* RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m in Sources */,
|
||||
|
||||
+2
-82
@@ -166,7 +166,6 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
}
|
||||
|
||||
@property (strong, nonatomic) UIAlertController *mxInAppNotification;
|
||||
@property (strong, nonatomic) UIAlertController *incomingCallNotification;
|
||||
|
||||
@property (nonatomic, nullable, copy) void (^registrationForRemoteNotificationsCompletion)(NSError *);
|
||||
|
||||
@@ -565,13 +564,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
// Enable error notifications
|
||||
isErrorNotificationSuspended = NO;
|
||||
|
||||
// Restore call alert if any
|
||||
if (_incomingCallNotification)
|
||||
{
|
||||
NSLog(@"[AppDelegate] restoreInitialDisplay: keep visible incoming call alert");
|
||||
[self showNotificationAlert:_incomingCallNotification];
|
||||
}
|
||||
else if (noCallSupportAlert)
|
||||
if (noCallSupportAlert)
|
||||
{
|
||||
NSLog(@"[AppDelegate] restoreInitialDisplay: keep visible noCall support alert");
|
||||
[self showNotificationAlert:noCallSupportAlert];
|
||||
@@ -1848,81 +1841,8 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
|
||||
currentCallViewController = [CallViewController callViewController:mxCall];
|
||||
currentCallViewController.delegate = self;
|
||||
|
||||
if (mxCall.isIncoming)
|
||||
{
|
||||
// Prompt user before presenting the call view controller
|
||||
NSString *callPromptFormat = mxCall.isVideoCall ? NSLocalizedStringFromTable(@"call_incoming_video_prompt", @"Vector", nil) : NSLocalizedStringFromTable(@"call_incoming_voice_prompt", @"Vector", nil);
|
||||
NSString *callerName = currentCallViewController.peer.displayname;
|
||||
if (!callerName.length)
|
||||
{
|
||||
callerName = currentCallViewController.peer.userId;
|
||||
}
|
||||
NSString *callPrompt = [NSString stringWithFormat:callPromptFormat, callerName];
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
|
||||
// Removing existing notification (if any)
|
||||
[_incomingCallNotification dismissViewControllerAnimated:NO completion:nil];
|
||||
|
||||
|
||||
|
||||
_incomingCallNotification = [UIAlertController alertControllerWithTitle:callPrompt
|
||||
message:nil
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[_incomingCallNotification addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"decline", @"Vector", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
|
||||
// Reject the call.
|
||||
// Note: Do not reset the incoming call notification before this operation, because it is used to release properly the dismissed call view controller.
|
||||
if (self->currentCallViewController)
|
||||
{
|
||||
[self->currentCallViewController onButtonPressed:self->currentCallViewController.rejectCallButton];
|
||||
|
||||
currentCallViewController = nil;
|
||||
}
|
||||
|
||||
self.incomingCallNotification = nil;
|
||||
|
||||
mxCall.delegate = nil;
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[_incomingCallNotification addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"accept", @"Vector", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
|
||||
self.incomingCallNotification = nil;
|
||||
|
||||
if (self->currentCallViewController)
|
||||
{
|
||||
[self->currentCallViewController onButtonPressed:self->currentCallViewController.answerCallButton];
|
||||
|
||||
[self presentCallViewController:nil];
|
||||
}
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[_incomingCallNotification mxk_setAccessibilityIdentifier:@"AppDelegateIncomingCallAlert"];
|
||||
[self showNotificationAlert:_incomingCallNotification];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self presentCallViewController:nil];
|
||||
}
|
||||
[self presentCallViewController:nil];
|
||||
}
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
@@ -478,6 +478,8 @@
|
||||
// Call
|
||||
"call_incoming_voice_prompt" = "Incoming voice call from %@";
|
||||
"call_incoming_video_prompt" = "Incoming video call from %@";
|
||||
"call_incoming_voice" = "Incoming call...";
|
||||
"call_incoming_video" = "Incoming video call...";
|
||||
"call_already_displayed" = "There is already a call in progress.";
|
||||
"call_jitsi_error" = "Failed to join the conference call.";
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
#import "RiotNavigationController.h"
|
||||
|
||||
#import "IncomingCallView.h"
|
||||
|
||||
@interface CallViewController ()
|
||||
{
|
||||
// Display a gradient view above the screen
|
||||
@@ -196,6 +198,37 @@
|
||||
gradientMaskLayer = nil;
|
||||
}
|
||||
|
||||
- (UIView *)createIncomingCallView
|
||||
{
|
||||
NSString *avatarThumbURL = [self.mainSession.matrixRestClient urlOfContentThumbnail:self.peer.avatarUrl
|
||||
toFitViewSize:IncomingCallView.callerAvatarSize
|
||||
withMethod:MXThumbnailingMethodCrop];
|
||||
|
||||
NSString *callInfo;
|
||||
if (self.mxCall.isVideoCall)
|
||||
callInfo = NSLocalizedStringFromTable(@"call_incoming_video", @"Vector", nil);
|
||||
else
|
||||
callInfo = NSLocalizedStringFromTable(@"call_incoming_voice", @"Vector", nil);
|
||||
|
||||
IncomingCallView *incomingCallView = [[IncomingCallView alloc] initWithCallerAvatarURL:avatarThumbURL
|
||||
placeholderImage:self.picturePlaceholder
|
||||
callerName:self.peer.displayname
|
||||
callInfo:callInfo];
|
||||
|
||||
// Incoming call is retained by call vc so use weak to avoid retain cycle
|
||||
__weak typeof(self) weakSelf = self;
|
||||
|
||||
incomingCallView.onAnswer = ^{
|
||||
[weakSelf onButtonPressed:weakSelf.answerCallButton];
|
||||
};
|
||||
|
||||
incomingCallView.onReject = ^{
|
||||
[weakSelf onButtonPressed:weakSelf.rejectCallButton];
|
||||
};
|
||||
|
||||
return incomingCallView;
|
||||
}
|
||||
|
||||
#pragma mark - MXCallDelegate
|
||||
|
||||
- (void)call:(MXCall *)call didEncounterError:(NSError *)error
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface CircleButton : UIButton
|
||||
|
||||
/**
|
||||
Background color that is used for highlighted state
|
||||
|
||||
By default the same as borderColor
|
||||
*/
|
||||
@property (nonatomic) UIColor *highlightBackgroundColor;
|
||||
|
||||
/**
|
||||
Background color that is used for normal state
|
||||
|
||||
By default white
|
||||
*/
|
||||
@property (nonatomic) UIColor *defaultBackgroundColor;
|
||||
|
||||
/**
|
||||
Tint color that is used for highlighted state
|
||||
|
||||
By default is white
|
||||
*/
|
||||
@property (nonatomic) UIColor *highlightTintColor;
|
||||
|
||||
/**
|
||||
Tint color that is used for normal state
|
||||
|
||||
By default is the same as borderColor
|
||||
*/
|
||||
@property (nonatomic) UIColor *defaultTintColor;
|
||||
|
||||
- (instancetype)initWithImage:(UIImage *)image borderColor:(UIColor *)borderColor;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "CircleButton.h"
|
||||
|
||||
@implementation CircleButton
|
||||
|
||||
- (instancetype)initWithImage:(UIImage *)image borderColor:(UIColor *)borderColor
|
||||
{
|
||||
self = [[super class] buttonWithType:UIButtonTypeCustom];
|
||||
|
||||
self.adjustsImageWhenDisabled = NO;
|
||||
self.adjustsImageWhenHighlighted = NO;
|
||||
|
||||
self.layer.borderWidth = 1.0;
|
||||
self.layer.borderColor = borderColor.CGColor;
|
||||
|
||||
self.defaultBackgroundColor = [UIColor whiteColor];
|
||||
self.highlightTintColor = [UIColor whiteColor];
|
||||
|
||||
self.highlightBackgroundColor = borderColor;
|
||||
self.defaultTintColor = borderColor;
|
||||
self.tintColor = borderColor;
|
||||
|
||||
[self setImage:[image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setDefaultBackgroundColor:(UIColor *)defaultBackgroundColor
|
||||
{
|
||||
_defaultBackgroundColor = defaultBackgroundColor;
|
||||
self.backgroundColor = defaultBackgroundColor;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
self.layer.cornerRadius = CGRectGetWidth(self.bounds) / 2.0;
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
[super touchesBegan:touches withEvent:event];
|
||||
[self animateBackgroundColor:self.highlightBackgroundColor tintColor:self.highlightTintColor];
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
[super touchesEnded:touches withEvent:event];
|
||||
[self animateBackgroundColor:self.defaultBackgroundColor tintColor:self.defaultTintColor];
|
||||
}
|
||||
|
||||
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
[super touchesCancelled:touches withEvent:event];
|
||||
[self animateBackgroundColor:self.defaultBackgroundColor tintColor:self.defaultTintColor];
|
||||
}
|
||||
|
||||
- (void)animateBackgroundColor:(UIColor *)color tintColor:(UIColor *)tintColor
|
||||
{
|
||||
[UIView animateWithDuration:0.25
|
||||
delay:0.0
|
||||
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction
|
||||
animations:^{
|
||||
self.backgroundColor = color;
|
||||
self.tintColor = tintColor;
|
||||
}
|
||||
completion:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void (^IncomingCallViewAction)();
|
||||
|
||||
@interface IncomingCallView : UIView
|
||||
|
||||
/**
|
||||
Size that is applied to displayed user avatar
|
||||
*/
|
||||
@property (class, readonly) CGSize callerAvatarSize;
|
||||
|
||||
/**
|
||||
Block which is performed on call answer action
|
||||
*/
|
||||
@property (nonatomic, nullable, copy) IncomingCallViewAction onAnswer;
|
||||
|
||||
/**
|
||||
Block which is performed on call reject
|
||||
*/
|
||||
@property (nonatomic, nullable, copy) IncomingCallViewAction onReject;
|
||||
|
||||
- (instancetype)initWithCallerAvatarURL:(NSString *)callerAvatarURL
|
||||
placeholderImage:(UIImage *)placeholderImage
|
||||
callerName:(NSString *)callerName
|
||||
callInfo:(NSString *)callInfo;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "IncomingCallView.h"
|
||||
|
||||
#import <MatrixKit/MXKImageView.h>
|
||||
#import <MatrixSDK/MXMediaManager.h>
|
||||
|
||||
#import "CircleButton.h"
|
||||
#import "RiotDesignValues.h"
|
||||
|
||||
static const CGFloat kAvatarSize = 100.0;
|
||||
static const CGFloat kButtonSize = 80.0;
|
||||
|
||||
@interface IncomingCallView ()
|
||||
|
||||
@property (nonatomic) MXKImageView *callerImageView;
|
||||
@property (nonatomic) UILabel *callerNameLabel;
|
||||
@property (nonatomic) UILabel *callInfoLabel;
|
||||
|
||||
@property (nonatomic) CircleButton *answerButton;
|
||||
@property (nonatomic) UILabel *answerTitleLabel;
|
||||
|
||||
@property (nonatomic) CircleButton *rejectButton;
|
||||
@property (nonatomic) UILabel *rejectTitleLabel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation IncomingCallView
|
||||
|
||||
+ (CGSize)callerAvatarSize
|
||||
{
|
||||
return CGSizeMake(kAvatarSize, kAvatarSize);
|
||||
}
|
||||
|
||||
- (instancetype)initWithCallerAvatarURL:(NSString *)callerAvatarURL placeholderImage:(UIImage *)placeholderImage callerName:(NSString *)callerName callInfo:(NSString *)callInfo
|
||||
{
|
||||
self = [super initWithFrame:CGRectZero];
|
||||
if (self)
|
||||
{
|
||||
self.backgroundColor = kRiotPrimaryBgColor;
|
||||
self.opaque = YES;
|
||||
|
||||
self.callerImageView = [[MXKImageView alloc] init];
|
||||
self.callerImageView.backgroundColor = kRiotPrimaryBgColor;
|
||||
self.callerImageView.clipsToBounds = YES;
|
||||
self.callerImageView.mediaFolder = kMXMediaManagerAvatarThumbnailFolder;
|
||||
self.callerImageView.enableInMemoryCache = YES;
|
||||
[self.callerImageView setImageURL:callerAvatarURL
|
||||
withType:nil
|
||||
andImageOrientation:UIImageOrientationUp
|
||||
previewImage:placeholderImage];
|
||||
|
||||
self.callerNameLabel = [[UILabel alloc] init];
|
||||
self.callerNameLabel.backgroundColor = kRiotPrimaryBgColor;
|
||||
self.callerNameLabel.textColor = kRiotPrimaryTextColor;
|
||||
self.callerNameLabel.font = [UIFont systemFontOfSize:24.0 weight:UIFontWeightMedium];
|
||||
self.callerNameLabel.text = callerName;
|
||||
self.callerNameLabel.textAlignment = NSTextAlignmentCenter;
|
||||
|
||||
self.callInfoLabel = [[UILabel alloc] init];
|
||||
self.callInfoLabel.backgroundColor = kRiotPrimaryBgColor;
|
||||
self.callInfoLabel.textColor = kRiotSecondaryTextColor;
|
||||
self.callInfoLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular];
|
||||
self.callInfoLabel.text = callInfo;
|
||||
self.callInfoLabel.textAlignment = NSTextAlignmentCenter;
|
||||
|
||||
UIColor *answerButtonBorderColor = kRiotColorGreen;
|
||||
|
||||
self.answerButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"voice_call_icon"]
|
||||
borderColor:answerButtonBorderColor];
|
||||
self.answerButton.defaultBackgroundColor = kRiotPrimaryBgColor;
|
||||
[self.answerButton addTarget:self action:@selector(didTapAnswerButton) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
self.answerTitleLabel = [[UILabel alloc] init];
|
||||
self.answerTitleLabel.backgroundColor = kRiotPrimaryBgColor;
|
||||
self.answerTitleLabel.textColor = answerButtonBorderColor;
|
||||
self.answerTitleLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular];
|
||||
self.answerTitleLabel.text = NSLocalizedStringFromTable(@"accept", @"Vector", nil);
|
||||
|
||||
UIColor *rejectButtonBorderColor = kRiotColorPinkRed;
|
||||
|
||||
self.rejectButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"call_hangup_icon"]
|
||||
borderColor:rejectButtonBorderColor];
|
||||
self.rejectButton.defaultBackgroundColor = kRiotPrimaryBgColor;
|
||||
[self.rejectButton addTarget:self action:@selector(didTapRejectButton) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
self.rejectTitleLabel = [[UILabel alloc] init];
|
||||
self.rejectTitleLabel.backgroundColor = kRiotPrimaryBgColor;
|
||||
self.rejectTitleLabel.textColor = rejectButtonBorderColor;
|
||||
self.rejectTitleLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular];
|
||||
self.rejectTitleLabel.text = NSLocalizedStringFromTable(@"decline", @"Vector", nil);
|
||||
|
||||
[self setupLayout];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
self.callerImageView.layer.cornerRadius = CGRectGetWidth(self.callerImageView.bounds) / 2.0;
|
||||
}
|
||||
|
||||
- (void)setupLayout
|
||||
{
|
||||
NSArray *views = @[self.callerImageView, self.callerNameLabel, self.callInfoLabel, self.answerButton, self.answerTitleLabel, self.rejectButton, self.rejectTitleLabel];
|
||||
for (UIView *view in views)
|
||||
{
|
||||
view.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self addSubview:view];
|
||||
}
|
||||
|
||||
[NSLayoutConstraint activateConstraints:@[
|
||||
[NSLayoutConstraint constraintWithItem:self.callerImageView
|
||||
attribute:NSLayoutAttributeTop
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self
|
||||
attribute:NSLayoutAttributeTop
|
||||
multiplier:1.0
|
||||
constant:62.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.callerImageView
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
multiplier:1.0
|
||||
constant:0.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.callerImageView
|
||||
attribute:NSLayoutAttributeWidth
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:kAvatarSize],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.callerImageView
|
||||
attribute:NSLayoutAttributeHeight
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.callerImageView
|
||||
attribute:NSLayoutAttributeWidth
|
||||
multiplier:1.0
|
||||
constant:0.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.callerNameLabel
|
||||
attribute:NSLayoutAttributeTop
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.callerImageView
|
||||
attribute:NSLayoutAttributeBottom
|
||||
multiplier:1.0
|
||||
constant:18.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.callerNameLabel
|
||||
attribute:NSLayoutAttributeLeading
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self
|
||||
attribute:NSLayoutAttributeLeading
|
||||
multiplier:1.0
|
||||
constant:15.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.callerNameLabel
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
multiplier:1.0
|
||||
constant:-15.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.callInfoLabel
|
||||
attribute:NSLayoutAttributeTop
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.callerNameLabel
|
||||
attribute:NSLayoutAttributeBottom
|
||||
multiplier:1.0
|
||||
constant:7.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.callInfoLabel
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
multiplier:1.0
|
||||
constant:0.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.callInfoLabel
|
||||
attribute:NSLayoutAttributeWidth
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.callerNameLabel
|
||||
attribute:NSLayoutAttributeWidth
|
||||
multiplier:1.0
|
||||
constant:0.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.rejectButton
|
||||
attribute:NSLayoutAttributeWidth
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:kButtonSize],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.rejectButton
|
||||
attribute:NSLayoutAttributeHeight
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.rejectButton
|
||||
attribute:NSLayoutAttributeWidth
|
||||
multiplier:1.0
|
||||
constant:0.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.rejectButton
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
multiplier:1.0
|
||||
constant:-22.5],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.rejectTitleLabel
|
||||
attribute:NSLayoutAttributeTop
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.rejectButton
|
||||
attribute:NSLayoutAttributeBottom
|
||||
multiplier:1.0
|
||||
constant:8.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.rejectTitleLabel
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.rejectButton
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
multiplier:1.0
|
||||
constant:0.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.rejectTitleLabel
|
||||
attribute:NSLayoutAttributeBottom
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self
|
||||
attribute:NSLayoutAttributeBottom
|
||||
multiplier:1.0
|
||||
constant:-16.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.answerButton
|
||||
attribute:NSLayoutAttributeWidth
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:kButtonSize],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.answerButton
|
||||
attribute:NSLayoutAttributeHeight
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.answerButton
|
||||
attribute:NSLayoutAttributeWidth
|
||||
multiplier:1.0
|
||||
constant:0.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.answerButton
|
||||
attribute:NSLayoutAttributeLeading
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
multiplier:1.0
|
||||
constant:22.5],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.answerTitleLabel
|
||||
attribute:NSLayoutAttributeTop
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.answerButton
|
||||
attribute:NSLayoutAttributeBottom
|
||||
multiplier:1.0
|
||||
constant:8.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.answerTitleLabel
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.answerButton
|
||||
attribute:NSLayoutAttributeCenterX
|
||||
multiplier:1.0
|
||||
constant:0.0],
|
||||
|
||||
[NSLayoutConstraint constraintWithItem:self.answerTitleLabel
|
||||
attribute:NSLayoutAttributeBottom
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self
|
||||
attribute:NSLayoutAttributeBottom
|
||||
multiplier:1.0
|
||||
constant:-16.0]
|
||||
]];
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
- (void)didTapAnswerButton
|
||||
{
|
||||
if (self.onAnswer)
|
||||
{
|
||||
self.onAnswer();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didTapRejectButton
|
||||
{
|
||||
if (self.onReject)
|
||||
{
|
||||
self.onReject();
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user