Introduce CallBar view management

This commit is contained in:
ismailgulek
2020-12-02 23:17:06 +03:00
parent c2e616b870
commit 50feecc4df
11 changed files with 366 additions and 116 deletions
+2 -1
View File
@@ -29,6 +29,7 @@
@protocol Configurable;
@protocol LegacyAppDelegateDelegate;
@class CallBar;
#pragma mark - Notifications
/**
@@ -238,7 +239,7 @@ JitsiViewControllerDelegate>
Call status window displayed when user goes back to app during a call.
*/
@property (nonatomic, readonly) UIWindow* callStatusBarWindow;
@property (nonatomic, readonly) UIButton* callStatusBarButton;
@property (nonatomic, readonly) CallBar* callBar;
#pragma mark - App version management
+72 -68
View File
@@ -90,7 +90,7 @@ NSString *const AppDelegateDidValidateEmailNotificationClientSecretKey = @"AppDe
NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUniversalLinkDidChangeNotification";
@interface LegacyAppDelegate () <GDPRConsentViewControllerDelegate, KeyVerificationCoordinatorBridgePresenterDelegate, ServiceTermsModalCoordinatorBridgePresenterDelegate, PushNotificationServiceDelegate, SetPinCoordinatorBridgePresenterDelegate, CallServiceDelegate>
@interface LegacyAppDelegate () <GDPRConsentViewControllerDelegate, KeyVerificationCoordinatorBridgePresenterDelegate, ServiceTermsModalCoordinatorBridgePresenterDelegate, PushNotificationServiceDelegate, SetPinCoordinatorBridgePresenterDelegate, CallServiceDelegate, CallBarDelegate>
{
/**
Reachability observer
@@ -3043,7 +3043,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
MXRoom *room = [_jitsiViewController.widget.mxSession roomWithRoomId:_jitsiViewController.widget.roomId];
NSString *btnTitle = [NSString stringWithFormat:NSLocalizedStringFromTable(@"active_call_details", @"Vector", nil), room.summary.displayname];
[self addCallStatusBar:btnTitle];
[self updateCallStatusBar:btnTitle];
if (completion)
{
@@ -3186,8 +3186,13 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
return result;
}
- (void)addCallStatusBar:(NSString*)buttonTitle
- (void)updateCallStatusBar:(NSString*)title
{
if (_callBar)
{
_callBar.title = title;
return;
}
// Add a call status bar
CGSize topBarSize = CGSizeMake([[UIScreen mainScreen] bounds].size.width, [self calculateCallStatusBarHeight]);
@@ -3195,42 +3200,20 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
_callStatusBarWindow.windowLevel = UIWindowLevelStatusBar;
// Create statusBarButton
_callStatusBarButton = [UIButton buttonWithType:UIButtonTypeCustom];
_callStatusBarButton.frame = CGRectMake(0, 0, topBarSize.width, topBarSize.height);
[_callStatusBarButton setTitle:buttonTitle forState:UIControlStateNormal];
[_callStatusBarButton setTitle:buttonTitle forState:UIControlStateHighlighted];
_callStatusBarButton.titleLabel.textColor = ThemeService.shared.theme.backgroundColor;
_callStatusBarButton.titleLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightMedium];
[_callStatusBarButton setBackgroundColor:ThemeService.shared.theme.tintColor];
[_callStatusBarButton addTarget:self action:@selector(onCallStatusBarButtonPressed) forControlEvents:UIControlEventTouchUpInside];
_callBar = [CallBar instantiate];
_callBar.frame = CGRectMake(0, 0, topBarSize.width, topBarSize.height);
_callBar.title = title;
_callBar.backgroundColor = ThemeService.shared.theme.tintColor;
_callBar.delegate = self;
// Place button into the new window
[_callStatusBarButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[_callStatusBarWindow addSubview:_callStatusBarButton];
// Force callStatusBarButton to fill the window (to handle auto-layout in case of screen rotation)
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:_callStatusBarButton
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:_callStatusBarWindow
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:0];
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:_callStatusBarButton
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:_callStatusBarWindow
attribute:NSLayoutAttributeHeight
multiplier:1.0
constant:0];
[NSLayoutConstraint activateConstraints:@[widthConstraint, heightConstraint]];
[_callBar setTranslatesAutoresizingMaskIntoConstraints:NO];
[_callStatusBarWindow addSubview:_callBar];
// Force callBar to fill the window (to handle auto-layout in case of screen rotation)
[_callBar.widthAnchor constraintEqualToAnchor:_callStatusBarWindow.widthAnchor].active = YES;
[_callBar.heightAnchor constraintEqualToAnchor:_callStatusBarWindow.heightAnchor].active = YES;
_callStatusBarWindow.hidden = NO;
[self statusBarDidChangeFrame];
@@ -3251,26 +3234,14 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
// Hide & destroy it
_callStatusBarWindow.hidden = YES;
[_callStatusBarButton removeFromSuperview];
_callStatusBarButton = nil;
[_callBar removeFromSuperview];
_callBar = nil;
_callStatusBarWindow = nil;
[self statusBarDidChangeFrame];
}
}
- (void)onCallStatusBarButtonPressed
{
if ([_callService callStatusBarButtonTapped])
{
return;
}
else if (_jitsiViewController)
{
[self presentJitsiViewController:nil];
}
}
- (void)statusBarDidChangeFrame
{
UIApplication *app = [UIApplication sharedApplication];
@@ -3307,20 +3278,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
}
}
UIEdgeInsets callBarButtonContentEdgeInsets = UIEdgeInsetsZero;
if (@available(iOS 11.0, *))
{
callBarButtonContentEdgeInsets = UIApplication.sharedApplication.keyWindow.safeAreaInsets;
// should override top inset
callBarButtonContentEdgeInsets.top = callStatusBarHeight - CALL_STATUS_BAR_HEIGHT;
// should ignore bottom inset
callBarButtonContentEdgeInsets.bottom = 0.0;
// should keep left, and right insets as original
}
_callStatusBarButton.contentEdgeInsets = callBarButtonContentEdgeInsets;
// Apply the vertical offset due to call status bar
rootControllerFrame.origin.y = callStatusBarHeight;
rootControllerFrame.size.height -= callStatusBarHeight;
@@ -4490,10 +4447,43 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
}
}
- (void)callService:(CallService *)service presentCallBarFor:(CallViewController *)viewController completion:(void (^)(void))completion
- (void)callService:(CallService *)service presentCallBarFor:(CallViewController *)activeCallViewController numberOfPausedCalls:(NSUInteger)numberOfPausedCalls completion:(void (^)(void))completion
{
NSString *btnTitle = [NSString stringWithFormat:NSLocalizedStringFromTable(@"active_call_details", @"Vector", nil), viewController.callerNameLabel.text];
[self addCallStatusBar:btnTitle];
NSString *btnTitle;
if (activeCallViewController)
{
// TODO: Add timer for active call duration
if (numberOfPausedCalls == 0)
{
// only one active
btnTitle = [NSString stringWithFormat:NSLocalizedStringFromTable(@"callbar_only_single_active", @"Vector", nil), activeCallViewController.callStatusLabel.text];
}
else if (numberOfPausedCalls == 1)
{
// one active and one paused
btnTitle = [NSString stringWithFormat:NSLocalizedStringFromTable(@"callbar_active_and_single_paused", @"Vector", nil), activeCallViewController.callStatusLabel.text];
}
else
{
// one active and multiple paused
btnTitle = [NSString stringWithFormat:NSLocalizedStringFromTable(@"callbar_active_and_multiple_paused", @"Vector", nil), activeCallViewController.callStatusLabel.text, @(numberOfPausedCalls)];
}
}
else
{
// no active calls
if (numberOfPausedCalls == 1)
{
btnTitle = NSLocalizedStringFromTable(@"callbar_only_single_paused", @"Vector", nil);
}
else
{
btnTitle = [NSString stringWithFormat:NSLocalizedStringFromTable(@"callbar_only_multiple_paused", @"Vector", nil), @(numberOfPausedCalls)];
}
}
[self updateCallStatusBar:btnTitle];
if (completion)
{
@@ -4501,7 +4491,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
}
}
- (void)callService:(CallService *)service dismissCallBarFor:(CallViewController *)viewController completion:(void (^)(void))completion
- (void)callService:(CallService *)service dismissCallBar:(void (^)(void))completion
{
[self removeCallStatusBar];
@@ -4511,4 +4501,18 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
}
}
#pragma mark - CallBarDelegate
- (void)callBarDidTapReturnButton:(CallBar *)callBar
{
if ([_callService callStatusBarButtonTapped])
{
return;
}
else if (_jitsiViewController)
{
[self presentJitsiViewController:nil];
}
}
@end
@@ -0,0 +1,52 @@
//
// Copyright 2020 New Vector 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 Foundation
import Reusable
@objc protocol CallBarDelegate: class {
func callBarDidTapReturnButton(_ callBar: CallBar)
}
@objcMembers
class CallBar: UIView, NibLoadable {
@IBOutlet private weak var callIcon: UIImageView! {
didSet {
callIcon.image = Asset.Images.voiceCallHangonIcon.image.vc_tintedImage(usingColor: .white)
}
}
@IBOutlet private weak var titleLabel: UILabel!
@IBOutlet private weak var returnButton: UIButton!
weak var delegate: CallBarDelegate?
static func instantiate() -> CallBar {
return CallBar.loadFromNib()
}
var title: String? {
get {
return titleLabel.text
} set {
titleLabel.text = newValue
}
}
@IBAction private func returnButtonTapped(_ sender: UIButton) {
delegate?.callBarDidTapReturnButton(self)
}
}
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17126"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="CallBar" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="eee-sW-qFO">
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="voice_call_hangon_icon" translatesAutoresizingMaskIntoConstraints="NO" id="cuO-6F-uXq">
<rect key="frame" x="0.0" y="0.0" width="44" height="44"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" secondItem="cuO-6F-uXq" secondAttribute="height" multiplier="1:1" id="CgQ-jX-f2t"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="249" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4TV-K4-7lO">
<rect key="frame" x="44" y="8" width="303" height="28"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="UUZ-sl-L6q">
<rect key="frame" x="355" y="0.0" width="59" height="44"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="contentEdgeInsets" minX="8" minY="8" maxX="8" maxY="8"/>
<state key="normal" title="Return"/>
<connections>
<action selector="returnButtonTapped:" destination="iN0-l3-epB" eventType="touchUpInside" id="VJx-cV-NtX"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="cuO-6F-uXq" firstAttribute="leading" secondItem="eee-sW-qFO" secondAttribute="leading" id="1Md-B3-CA1"/>
<constraint firstAttribute="bottom" secondItem="cuO-6F-uXq" secondAttribute="bottom" id="Fe6-FC-Lkh"/>
<constraint firstItem="UUZ-sl-L6q" firstAttribute="top" secondItem="eee-sW-qFO" secondAttribute="top" id="HSs-7b-rXw"/>
<constraint firstAttribute="bottom" secondItem="UUZ-sl-L6q" secondAttribute="bottom" id="MgQ-Px-CRu"/>
<constraint firstItem="4TV-K4-7lO" firstAttribute="leading" secondItem="cuO-6F-uXq" secondAttribute="trailing" id="Pfy-hd-a8d"/>
<constraint firstAttribute="trailing" secondItem="UUZ-sl-L6q" secondAttribute="trailing" id="aqk-h6-34r"/>
<constraint firstAttribute="bottom" secondItem="4TV-K4-7lO" secondAttribute="bottom" constant="8" id="cij-lT-Nw6"/>
<constraint firstAttribute="height" constant="44" id="g8Q-T8-geN"/>
<constraint firstItem="4TV-K4-7lO" firstAttribute="top" secondItem="eee-sW-qFO" secondAttribute="top" constant="8" id="lfW-G9-DaP"/>
<constraint firstItem="UUZ-sl-L6q" firstAttribute="leading" secondItem="4TV-K4-7lO" secondAttribute="trailing" constant="8" id="niz-VT-cYY"/>
<constraint firstItem="cuO-6F-uXq" firstAttribute="top" secondItem="eee-sW-qFO" secondAttribute="top" id="v7k-1F-UR7"/>
</constraints>
</view>
</subviews>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<color key="backgroundColor" red="0.011764705882352941" green="0.70196078431372544" blue="0.50588235294117645" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="eee-sW-qFO" secondAttribute="trailing" id="8uk-4g-uhK"/>
<constraint firstAttribute="bottom" secondItem="eee-sW-qFO" secondAttribute="bottom" id="dPh-ko-WYf"/>
<constraint firstItem="eee-sW-qFO" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="tfp-6O-DDi"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="callIcon" destination="cuO-6F-uXq" id="A3y-xa-XHu"/>
<outlet property="returnButton" destination="UUZ-sl-L6q" id="baV-ub-2f1"/>
<outlet property="titleLabel" destination="4TV-K4-7lO" id="ZkY-wt-1OH"/>
</connections>
<point key="canvasLocation" x="137.68115942028987" y="-187.5"/>
</view>
</objects>
<resources>
<image name="voice_call_hangon_icon" width="24" height="24"/>
</resources>
</document>