Move the "Your camera is off" indicator up to GroupCallViewController

...so it can be constrained to not overlap the call header or call
controls when in larger font sizes. Additionally, the new view uses a
smaller font, and a horizontal layout for the icon + label when on
small screens.
This commit is contained in:
Jordan Rose 2022-08-19 12:15:27 -07:00
parent ecc48d7935
commit 2bb1f6c22a
3 changed files with 49 additions and 13 deletions

View File

@ -119,7 +119,8 @@ class CallControls: UIView {
addSubview(controlsStack)
controlsStack.autoPinWidthToSuperview()
controlsStack.autoPinEdge(toSuperviewSafeArea: .bottom, withInset: 56)
controlsStack.autoPinEdge(toSuperviewSafeArea: .bottom, withInset: 40, relation: .lessThanOrEqual)
controlsStack.autoPinEdge(toSuperviewSafeArea: .bottom, withInset: 56).priority = .defaultHigh - 1
controlsStack.autoPinEdge(toSuperviewEdge: .top)
updateControls()

View File

@ -124,7 +124,6 @@ class GroupCallLocalMemberView: GroupCallMemberView {
let videoView = LocalVideoView()
let videoOffIndicatorImage = UIImageView()
let videoOffLabel = UILabel()
var videoOffIndicatorWidth: CGFloat {
if width > 102 {
@ -163,15 +162,6 @@ class GroupCallLocalMemberView: GroupCallMemberView {
videoOffIndicatorImage.autoMatch(.height, to: .width, of: videoOffIndicatorImage)
videoOffIndicatorImage.autoCenterInSuperview()
videoOffLabel.font = .ows_dynamicTypeSubheadline
videoOffLabel.text = NSLocalizedString("CALLING_MEMBER_VIEW_YOUR_CAMERA_IS_OFF",
comment: "Indicates to the user that their camera is currently off.")
videoOffLabel.textAlignment = .center
videoOffLabel.textColor = Theme.darkThemePrimaryColor
noVideoView.addSubview(videoOffLabel)
videoOffLabel.autoPinWidthToSuperview()
videoOffLabel.autoPinEdge(.top, to: .bottom, of: videoOffIndicatorImage, withOffset: 10)
videoView.contentMode = .scaleAspectFill
insertSubview(videoView, belowSubview: muteIndicatorImage)
videoView.frame = bounds
@ -193,8 +183,8 @@ class GroupCallLocalMemberView: GroupCallMemberView {
videoView.captureSession = call.videoCaptureController.captureSession
noVideoView.isHidden = !videoView.isHidden
videoOffLabel.isHidden = !videoView.isHidden || !isFullScreen
videoOffIndicatorImage.isHidden = !videoView.isHidden
// In full-screen mode the image is shown as part of the "Your camera is off" message.
videoOffIndicatorImage.isHidden = noVideoView.isHidden || isFullScreen
guard let localAddress = tsAccountManager.localAddress else {
return owsFailDebug("missing local address")

View File

@ -13,6 +13,7 @@ class GroupCallViewController: UIViewController {
private let call: SignalCall
private var groupCall: GroupCall { call.groupCall }
private lazy var callControls = CallControls(call: call, delegate: self)
private lazy var noVideoIndicatorView: UIStackView = createNoVideoIndicatorView()
private lazy var callHeader = CallHeader(call: call, delegate: self)
private lazy var notificationView = GroupCallNotificationView(call: call)
@ -164,12 +165,19 @@ class GroupCallViewController: UIViewController {
callHeader.autoPinWidthToSuperview()
callHeader.autoPinEdge(toSuperviewEdge: .top)
view.addSubview(noVideoIndicatorView)
noVideoIndicatorView.autoHCenterInSuperview()
// Be flexible on the vertical centering on a cramped screen.
noVideoIndicatorView.autoVCenterInSuperview().priority = .defaultLow
noVideoIndicatorView.autoPinEdge(.top, to: .bottom, of: callHeader, withOffset: 8, relation: .greaterThanOrEqual)
view.addSubview(notificationView)
notificationView.autoPinEdgesToSuperviewEdges()
view.addSubview(callControls)
callControls.autoPinWidthToSuperview()
callControls.autoPinEdge(toSuperviewEdge: .bottom)
callControls.autoPinEdge(.top, to: .bottom, of: noVideoIndicatorView, withOffset: 8, relation: .greaterThanOrEqual)
view.addSubview(videoOverflow)
videoOverflow.autoPinEdge(toSuperviewEdge: .leading)
@ -188,6 +196,39 @@ class GroupCallViewController: UIViewController {
updateCallUI()
}
private func createNoVideoIndicatorView() -> UIStackView {
let icon = UIImageView()
icon.contentMode = .scaleAspectFit
icon.setTemplateImage(#imageLiteral(resourceName: "video-off-solid-28"), tintColor: .ows_white)
let label = UILabel()
label.font = .ows_dynamicTypeCaption1
label.text = NSLocalizedString("CALLING_MEMBER_VIEW_YOUR_CAMERA_IS_OFF",
comment: "Indicates to the user that their camera is currently off.")
label.textAlignment = .center
label.textColor = Theme.darkThemePrimaryColor
let container = UIStackView(arrangedSubviews: [icon, label])
if UIDevice.current.isIPhone5OrShorter {
// Use a horizontal layout to save on vertical space.
// Allow the icon to shrink below its natural size of 28pt...
icon.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
container.axis = .horizontal
container.spacing = 4
// ...by always matching the label's height.
container.alignment = .fill
} else {
// Use a simple vertical layout.
icon.autoSetDimensions(to: CGSize(square: 28))
container.axis = .vertical
container.spacing = 10
container.alignment = .center
label.autoPinWidthToSuperview()
}
return container
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
@ -411,6 +452,10 @@ class GroupCallViewController: UIViewController {
guard !isCallMinimized else { return }
let showNoVideoIndicator = groupCall.remoteDeviceStates.isEmpty && groupCall.isOutgoingVideoMuted
// Hide the subviews of this view to collapse the stack.
noVideoIndicatorView.subviews.forEach { $0.isHidden = !showNoVideoIndicator }
let hideRemoteControls = shouldRemoteVideoControlsBeHidden && !groupCall.remoteDeviceStates.isEmpty
let remoteControlsAreHidden = callControls.isHidden && callHeader.isHidden
if hideRemoteControls != remoteControlsAreHidden {