Present action sheet when user requests info about error

Also, add mising GroupCallErrorView.swift file from last commit
This commit is contained in:
Michelle Linington 2020-11-25 13:34:26 -08:00
parent 85ac316064
commit 305017bcce
6 changed files with 217 additions and 5 deletions

View File

@ -0,0 +1,135 @@
//
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
//
import Foundation
class GroupCallErrorView: UIView {
// MARK: - Interface
var forceCompactAppearance: Bool = false {
didSet { configure() }
}
var iconImage: UIImage? {
didSet {
if let iconImage = iconImage {
iconView.setTemplateImage(iconImage, tintColor: .ows_white)
miniButton.setTemplateImage(iconImage, tintColor: .ows_white)
} else {
iconView.image = nil
miniButton.setImage(nil, for: .normal)
}
}
}
var labelText: String? {
didSet {
label.text = labelText
}
}
var userTapAction: ((GroupCallErrorView) -> Void)?
func resetConfiguration() {
iconImage = nil
labelText = nil
userTapAction = nil
}
// MARK: - Views
private let iconView: UIImageView = {
let view = UIImageView()
view.setTemplateImageName("error-solid-16", tintColor: .ows_white)
return view
}()
private let label: UILabel = {
let label = UILabel()
label.font = UIFont.ows_dynamicTypeSubheadline
label.textAlignment = .center
label.textColor = .ows_white
label.numberOfLines = 0
return label
}()
private let button: UIButton = {
let buttonLabel = NSLocalizedString(
"GROUP_CALL_ERROR_DETAILS",
comment: "A button to receive more info about not seeing a participant in group call grid")
let button = UIButton()
button.backgroundColor = UIColor.darkGray
button.layer.cornerRadius = 16
button.titleLabel?.textAlignment = .center
button.contentEdgeInsets = UIEdgeInsets(top: 3, leading: 12, bottom: 3, trailing: 12)
button.clipsToBounds = true
button.setTitle(buttonLabel, for: .normal)
button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
return button
}()
private let miniButton: UIButton = {
let button = UIButton()
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.setTemplateImageName("error-solid-16", tintColor: .ows_white)
button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
return button
}()
override init(frame: CGRect) {
super.init(frame: frame)
let stackView = UIStackView(arrangedSubviews: [
iconView,
label,
button,
])
stackView.axis = .vertical
stackView.alignment = .center
stackView.distribution = .fill
stackView.setCustomSpacing(12, after: iconView)
stackView.setCustomSpacing(16, after: label)
addSubview(stackView)
stackView.autoPinWidthToSuperviewMargins()
stackView.autoVCenterInSuperview()
stackView.autoPinEdge(toSuperviewMargin: .top, relation: .greaterThanOrEqual)
stackView.autoPinEdge(toSuperviewMargin: .bottom, relation: .greaterThanOrEqual)
iconView.autoSetDimensions(to: CGSize(width: 24, height: 24))
addSubview(miniButton)
miniButton.autoSetDimensions(to: CGSize(width: 24, height: 24))
miniButton.autoCenterInSuperview()
configure()
}
override var bounds: CGRect {
didSet { configure() }
}
override var frame: CGRect {
didSet { configure() }
}
private func configure() {
let isCompact = (bounds.width < 100) || (bounds.height < 100) || forceCompactAppearance
iconView.isHidden = isCompact
label.isHidden = isCompact
button.isHidden = isCompact
miniButton.isHidden = !isCompact
}
@objc
private func didTapButton() {
userTapAction?(self)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@ -5,7 +5,12 @@
import Foundation
import SignalRingRTC
protocol GroupCallMemberViewDelegate: class {
func memberView(_: GroupCallMemberView, userRequestedInfoAboutError: GroupCallMemberView.ErrorState)
}
class GroupCallMemberView: UIView {
weak var delegate: GroupCallMemberViewDelegate?
let noVideoView = UIView()
let backgroundAvatarView = UIImageView()
@ -66,6 +71,11 @@ class GroupCallMemberView: UIView {
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
enum ErrorState {
case blocked(SignalServiceAddress)
case noMediaKeys(SignalServiceAddress)
}
}
class GroupCallLocalMemberView: GroupCallMemberView {
@ -396,9 +406,14 @@ class GroupCallRemoteMemberView: GroupCallMemberView {
errorView.iconImage = image
errorView.labelText = label
errorView.userTapAction = { _ in
// TODO
Logger.info("Present alert controller for \(displayName)")
errorView.userTapAction = { [weak self] _ in
guard let self = self else { return }
if isBlocked {
self.delegate?.memberView(self, userRequestedInfoAboutError: .blocked(address))
} else {
self.delegate?.memberView(self, userRequestedInfoAboutError: .noMediaKeys(address))
}
}
}
}

View File

@ -6,6 +6,7 @@ import Foundation
import SignalRingRTC
class GroupCallVideoGrid: UICollectionView {
weak var memberViewDelegate: GroupCallMemberViewDelegate?
let layout: GroupCallVideoGridLayout
let call: SignalCall
init(call: SignalCall) {
@ -65,8 +66,8 @@ extension GroupCallVideoGrid: UICollectionViewDataSource {
return cell
}
cell.setMemberViewDelegate(memberViewDelegate)
cell.configure(call: call, device: remoteDevice)
return cell
}
}
@ -149,6 +150,10 @@ class GroupCallVideoGridCell: UICollectionViewCell {
func configureRemoteVideo(device: RemoteDeviceState) {
memberView.configureRemoteVideo(device: device)
}
func setMemberViewDelegate(_ delegate: GroupCallMemberViewDelegate?) {
memberView.delegate = delegate
}
}
extension Sequence where Element: RemoteDeviceState {

View File

@ -11,6 +11,7 @@ protocol GroupCallVideoOverflowDelegate: class {
}
class GroupCallVideoOverflow: UICollectionView {
weak var memberViewDelegate: GroupCallMemberViewDelegate?
weak var overflowDelegate: GroupCallVideoOverflowDelegate?
let call: SignalCall
@ -128,8 +129,8 @@ extension GroupCallVideoOverflow: UICollectionViewDataSource {
return cell
}
cell.setMemberViewDelegate(memberViewDelegate)
cell.configure(call: call, device: remoteDevice)
return cell
}
}
@ -186,4 +187,8 @@ class GroupCallVideoOverflowCell: UICollectionViewCell {
func configureRemoteVideo(device: RemoteDeviceState) {
memberView.configureRemoteVideo(device: device)
}
func setMemberViewDelegate(_ delegate: GroupCallMemberViewDelegate?) {
memberView.delegate = delegate
}
}

View File

@ -47,6 +47,11 @@ class GroupCallViewController: UIViewController {
super.init(nibName: nil, bundle: nil)
call.addObserverAndSyncState(observer: self)
videoGrid.memberViewDelegate = self
videoOverflow.memberViewDelegate = self
speakerView.delegate = self
localMemberView.delegate = self
}
@discardableResult
@ -588,3 +593,38 @@ extension GroupCallViewController: UIScrollViewDelegate {
}
}
}
extension GroupCallViewController: GroupCallMemberViewDelegate {
func memberView(_ view: GroupCallMemberView, userRequestedInfoAboutError error: GroupCallMemberView.ErrorState) {
let title: String
let message: String
switch error {
case let .blocked(address):
message = NSLocalizedString(
"GROUP_CALL_BLOCKED_ALERT_MESSAGE",
comment: "Message body for alert explaining that a group call participant is blocked")
let titleFormat = NSLocalizedString(
"GROUP_CALL_BLOCKED_ALERT_TITLE_FORMAT",
comment: "Title for alert explaining that a group call participant is blocked. Embeds {{ user's name }}")
let displayName = contactsManager.displayName(for: address)
title = String(format: titleFormat, [displayName])
case let .noMediaKeys(address):
message = NSLocalizedString(
"GROUP_CALL_NO_KEYS_ALERT_MESSAGE",
comment: "Message body for alert explaining that a group call participant cannot be displayed because of missing keys")
let titleFormat = NSLocalizedString(
"GROUP_CALL_NO_KEYS_ALERT_TITLE_FORMAT",
comment: "Title for alert explaining that a group call participant cannot be displayed because of missing keys. Embeds {{ user's name }}")
let displayName = contactsManager.displayName(for: address)
title = String(format: titleFormat, [displayName])
}
let actionSheet = ActionSheetController(title: title, message: message)
actionSheet.addAction(ActionSheetAction(title: CommonStrings.okButton))
presentActionSheet(actionSheet)
}
}

View File

@ -1522,6 +1522,12 @@
/* Message indicating that a feature can only be used by group admins. */
"GROUP_ADMIN_ONLY_WARNING" = "Only admins can change this option.";
/* Message body for alert explaining that a group call participant is blocked */
"GROUP_CALL_BLOCKED_ALERT_MESSAGE" = "Text TBD";
/* Title for alert explaining that a group call participant is blocked. Embeds {{ user's name }} */
"GROUP_CALL_BLOCKED_ALERT_TITLE_FORMAT" = "%@ is blocked";
/* String displayed in group call grid cell when a user is blocked. Embeds {user's name} */
"GROUP_CALL_BLOCKED_USER_FORMAT" = "%@ is blocked and will not receive your audio or video";
@ -1552,6 +1558,12 @@
/* String displayed in cell when media from a user can't be displayed in group call grid. Embeds {user's name} */
"GROUP_CALL_MISSING_MEDIA_KEYS_FORMAT" = "Can't receive audio & video from %@";
/* Message body for alert explaining that a group call participant cannot be displayed because of missing keys */
"GROUP_CALL_NO_KEYS_ALERT_MESSAGE" = "This may be because they have not verified your safety number change, there's a problem with their device, or they have blocked you.";
/* Title for alert explaining that a group call participant cannot be displayed because of missing keys. Embeds {{ user's name }} */
"GROUP_CALL_NO_KEYS_ALERT_TITLE_FORMAT" = "Can't receive audio and video from %@";
/* Text explaining that you are the only person currently in the group call */
"GROUP_CALL_NO_ONE_HERE" = "No one else is here";