Added the ability to resend and delete non-accepted invites

pull/894/head
Morgan Pretty 1 year ago
parent 7cc6e32ed9
commit 22e65c7224

@ -349,19 +349,17 @@ class EditGroupViewModel: SessionTableViewModel, NavigatableStateHolder, Editabl
trailingAccessory: {
switch (memberInfo.value.role, memberInfo.value.roleStatus) {
case (.admin, _), (.moderator, _): return nil
case (.standard, .failed), (.standard, .sending):
return .highlightingBackgroundLabel(
case (.standard, .failed), (.standard, .sending), (.standard, .pending):
return .highlightingBackgroundLabelAndRadio(
title: "context_menu_resend".localized(),
accessibility: Accessibility(
isSelected: selectedIdsSubject.value.contains(memberInfo.profileId),
labelAccessibility: Accessibility(
identifier: "Resend invite",
label: "Resend invite"
)
)
// Intentionally including the 'pending' state in here as we want admins to
// be able to remove pending members - to resend the admin will have to remove
// and re-add the member
case (.standard, .pending), (.standard, .accepted), (.zombie, _):
case (.standard, .accepted), (.zombie, _):
return .radio(
isSelected: selectedIdsSubject.value.contains(memberInfo.profileId)
)
@ -376,19 +374,22 @@ class EditGroupViewModel: SessionTableViewModel, NavigatableStateHolder, Editabl
),
backgroundStyle: .noBackgroundEdgeToEdge
),
onTap: { [weak self, selectedIdsSubject] in
switch (memberInfo.value.role, memberInfo.value.roleStatus) {
case (.moderator, _): return
case (.admin, _):
onTapView: { [weak self, selectedIdsSubject] targetView in
let didTapResend: Bool = (targetView is SessionHighlightingBackgroundLabel)
// TODO: updated group control messages are busted???
switch (memberInfo.value.role, memberInfo.value.roleStatus, didTapResend) {
case (.moderator, _, _): return
case (.admin, _, _):
self?.showToast(
text: "EDIT_GROUP_MEMBERS_ERROR_REMOVE_ADMIN".localized(),
backgroundColor: .backgroundSecondary
)
case (.standard, .failed), (.standard, .sending):
case (.standard, .failed, true), (.standard, .sending, true), (.standard, .pending, true):
self?.resendInvitation(memberId: memberInfo.profileId)
case (.standard, .pending), (.standard, .accepted), (.zombie, _):
case (.standard, .failed, _), (.standard, .sending, _), (.standard, .pending, _),
(.standard, .accepted, _), (.zombie, _, _):
if !selectedIdsSubject.value.contains(memberInfo.profileId) {
selectedIdsSubject.send(selectedIdsSubject.value.inserting(memberInfo.profileId))
}

@ -564,23 +564,56 @@ class SessionTableViewController<ViewModel>: BaseVC, UITableViewDataSource, UITa
return nil
}
// Retrieve the last touch location from the cell
let touchLocation: UITouch? = cell.lastTouchLocation
cell.lastTouchLocation = nil
switch (info.leadingAccessory, info.trailingAccessory) {
case (_, is SessionCell.AccessoryConfig.HighlightingBackgroundLabel):
return (!cell.trailingAccessoryView.isHidden ? cell.trailingAccessoryView : cell)
case (is SessionCell.AccessoryConfig.HighlightingBackgroundLabel, _):
return (!cell.leadingAccessoryView.isHidden ? cell.leadingAccessoryView : cell)
case (_, is SessionCell.AccessoryConfig.HighlightingBackgroundLabelAndRadio):
guard let touchLocation: UITouch = touchLocation else { return cell }
let localPoint: CGPoint = touchLocation.location(in: cell.trailingAccessoryView.highlightingBackgroundLabel)
guard
!cell.trailingAccessoryView.isHidden &&
cell.trailingAccessoryView.highlightingBackgroundLabel.bounds.contains(localPoint)
else { return (!cell.trailingAccessoryView.isHidden ? cell.trailingAccessoryView : cell) }
return cell.trailingAccessoryView.highlightingBackgroundLabel
case (is SessionCell.AccessoryConfig.HighlightingBackgroundLabelAndRadio, _):
guard let touchLocation: UITouch = touchLocation else { return cell }
let localPoint: CGPoint = touchLocation.location(in: cell.trailingAccessoryView.highlightingBackgroundLabel)
guard
!cell.leadingAccessoryView.isHidden &&
cell.leadingAccessoryView.highlightingBackgroundLabel.bounds.contains(localPoint)
else { return (!cell.leadingAccessoryView.isHidden ? cell.leadingAccessoryView : cell) }
return cell.leadingAccessoryView.highlightingBackgroundLabel
default:
return cell
}
}()
let maybeOldSelection: (Int, SessionCell.Info<TableItem>)? = section.elements
.enumerated()
.first(where: { index, info in
switch (info.leadingAccessory, info.trailingAccessory) {
case (_, let accessory as SessionCell.AccessoryConfig.Radio): return accessory.liveIsSelected()
case (let accessory as SessionCell.AccessoryConfig.Radio, _): return accessory.liveIsSelected()
case (_, let accessory as SessionCell.AccessoryConfig.HighlightingBackgroundLabelAndRadio):
return accessory.liveIsSelected()
case (let accessory as SessionCell.AccessoryConfig.HighlightingBackgroundLabelAndRadio, _):
return accessory.liveIsSelected()
default: return false
}
})

@ -110,6 +110,26 @@ public extension SessionCell.Accessory {
)
}
static func highlightingBackgroundLabelAndRadio(
title: String,
radioSize: SessionCell.AccessoryConfig.HighlightingBackgroundLabelAndRadio.Size = .medium,
isSelected: Bool? = nil,
liveIsSelected: (() -> Bool)? = nil,
wasSavedSelection: Bool = false,
accessibility: Accessibility? = nil,
labelAccessibility: Accessibility? = nil
) -> SessionCell.Accessory {
return SessionCell.AccessoryConfig.HighlightingBackgroundLabelAndRadio(
title: title,
radioSize: radioSize,
initialIsSelected: ((isSelected ?? liveIsSelected?()) ?? false),
liveIsSelected: (liveIsSelected ?? { (isSelected ?? false) }),
wasSavedSelection: wasSavedSelection,
accessibility: accessibility,
labelAccessibility: labelAccessibility
)
}
static func profile(
id: String,
size: ProfilePictureView.Size = .list,
@ -437,6 +457,81 @@ public extension SessionCell.AccessoryConfig {
}
}
// MARK: - HighlightingBackgroundLabelAndRadio
class HighlightingBackgroundLabelAndRadio: SessionCell.Accessory {
public enum Size: Hashable, Equatable {
case small
case medium
var borderSize: CGFloat {
switch self {
case .small: return 20
case .medium: return 26
}
}
var selectionSize: CGFloat {
switch self {
case .small: return 15
case .medium: return 20
}
}
}
public let title: String
public let size: Size
public let initialIsSelected: Bool
public let liveIsSelected: () -> Bool
public let wasSavedSelection: Bool
public let labelAccessibility: Accessibility?
override public var currentBoolValue: Bool { liveIsSelected() }
fileprivate init(
title: String,
radioSize: Size,
initialIsSelected: Bool,
liveIsSelected: @escaping () -> Bool,
wasSavedSelection: Bool,
accessibility: Accessibility?,
labelAccessibility: Accessibility?
) {
self.title = title
self.size = radioSize
self.initialIsSelected = initialIsSelected
self.liveIsSelected = liveIsSelected
self.wasSavedSelection = wasSavedSelection
self.labelAccessibility = labelAccessibility
super.init(accessibility: accessibility)
}
// MARK: - Conformance
override public func hash(into hasher: inout Hasher) {
title.hash(into: &hasher)
size.hash(into: &hasher)
initialIsSelected.hash(into: &hasher)
wasSavedSelection.hash(into: &hasher)
accessibility.hash(into: &hasher)
labelAccessibility.hash(into: &hasher)
}
override fileprivate func isEqual(to other: SessionCell.Accessory) -> Bool {
guard let rhs: HighlightingBackgroundLabelAndRadio = other as? HighlightingBackgroundLabelAndRadio else { return false }
return (
title == rhs.title &&
size == rhs.size &&
initialIsSelected == rhs.initialIsSelected &&
wasSavedSelection == rhs.wasSavedSelection &&
accessibility == rhs.accessibility &&
labelAccessibility == rhs.labelAccessibility
)
}
}
// MARK: - DisplayPicture
class DisplayPicture: SessionCell.Accessory {

@ -46,7 +46,8 @@ extension SessionCell {
private lazy var radioBorderViewHeightConstraint: NSLayoutConstraint = radioBorderView.set(.height, to: 0)
private lazy var radioBorderViewConstraints: [NSLayoutConstraint] = [
radioBorderView.pin(.top, to: .top, of: self),
radioBorderView.center(.horizontal, in: self),
radioBorderView.pin(.leading, to: .leading, of: self, withInset: Values.smallSpacing),
radioBorderView.pin(.trailing, to: .trailing, of: self, withInset: -Values.smallSpacing),
radioBorderView.pin(.bottom, to: .bottom, of: self)
]
private lazy var highlightingBackgroundLabelConstraints: [NSLayoutConstraint] = [
@ -55,6 +56,14 @@ extension SessionCell {
highlightingBackgroundLabel.pin(.trailing, to: .trailing, of: self, withInset: -Values.smallSpacing),
highlightingBackgroundLabel.pin(.bottom, to: .bottom, of: self)
]
private lazy var highlightingBackgroundLabelAndRadioConstraints: [NSLayoutConstraint] = [
highlightingBackgroundLabel.pin(.top, to: .top, of: self),
highlightingBackgroundLabel.pin(.leading, to: .leading, of: self, withInset: Values.smallSpacing),
highlightingBackgroundLabel.pin(.trailing, to: .leading, of: radioBorderView, withInset: -Values.smallSpacing),
highlightingBackgroundLabel.pin(.bottom, to: .bottom, of: self),
radioBorderView.center(.vertical, in: self),
radioBorderView.pin(.trailing, to: .trailing, of: self, withInset: -Values.smallSpacing),
]
private lazy var profilePictureViewConstraints: [NSLayoutConstraint] = [
profilePictureView.pin(.top, to: .top, of: self),
profilePictureView.pin(.leading, to: .leading, of: self),
@ -269,6 +278,7 @@ extension SessionCell {
radioBorderViewHeightConstraint.isActive = false
radioBorderViewConstraints.forEach { $0.isActive = false }
highlightingBackgroundLabelConstraints.forEach { $0.isActive = false }
highlightingBackgroundLabelAndRadioConstraints.forEach { $0.isActive = false }
profilePictureViewConstraints.forEach { $0.isActive = false }
searchBarConstraints.forEach { $0.isActive = false }
buttonConstraints.forEach { $0.isActive = false }
@ -431,7 +441,6 @@ extension SessionCell {
radioBorderViewWidthConstraint.constant = accessory.size.borderSize
radioBorderViewHeightConstraint.constant = accessory.size.borderSize
fixedWidthConstraint.isActive = true
radioViewWidthConstraint.isActive = true
radioViewHeightConstraint.isActive = true
radioBorderViewWidthConstraint.isActive = true
@ -448,6 +457,68 @@ extension SessionCell {
highlightingBackgroundLabelConstraints.forEach { $0.isActive = true }
minWidthConstraint.isActive = true
// MARK: -- HighlightingBackgroundLabelAndRadio
case let accessory as SessionCell.AccessoryConfig.HighlightingBackgroundLabelAndRadio:
let isSelected: Bool = accessory.liveIsSelected()
let wasOldSelection: Bool = (!isSelected && accessory.wasSavedSelection)
highlightingBackgroundLabel.accessibilityIdentifier = accessory.labelAccessibility?.identifier
highlightingBackgroundLabel.accessibilityLabel = accessory.labelAccessibility?.label
radioView.isAccessibilityElement = true
if isSelected || wasOldSelection {
radioView.accessibilityTraits.insert(.selected)
radioView.accessibilityValue = "selected"
} else {
radioView.accessibilityTraits.remove(.selected)
radioView.accessibilityValue = nil
}
highlightingBackgroundLabel.text = accessory.title
highlightingBackgroundLabel.themeTextColor = tintColor
highlightingBackgroundLabel.isHidden = false
radioBorderView.isHidden = false
radioBorderView.themeBorderColor = {
guard isEnabled else { return .radioButton_disabledBorder }
return (isSelected ?
.radioButton_selectedBorder :
.radioButton_unselectedBorder
)
}()
radioBorderView.layer.cornerRadius = (accessory.size.borderSize / 2)
radioView.accessibilityIdentifier = accessory.accessibility?.identifier
radioView.accessibilityLabel = accessory.accessibility?.label
radioView.alpha = (wasOldSelection ? 0.3 : 1)
radioView.isHidden = (!isSelected && !accessory.wasSavedSelection)
radioView.themeBackgroundColor = {
guard isEnabled else {
return (isSelected || wasOldSelection ?
.radioButton_disabledSelectedBackground :
.radioButton_disabledUnselectedBackground
)
}
return (isSelected || wasOldSelection ?
.radioButton_selectedBackground :
.radioButton_unselectedBackground
)
}()
radioView.layer.cornerRadius = (accessory.size.selectionSize / 2)
radioViewWidthConstraint.constant = accessory.size.selectionSize
radioViewHeightConstraint.constant = accessory.size.selectionSize
radioBorderViewWidthConstraint.constant = accessory.size.borderSize
radioBorderViewHeightConstraint.constant = accessory.size.borderSize
radioViewWidthConstraint.isActive = true
radioViewHeightConstraint.isActive = true
radioBorderViewWidthConstraint.isActive = true
radioBorderViewHeightConstraint.isActive = true
highlightingBackgroundLabelAndRadioConstraints.forEach { $0.isActive = true }
minWidthConstraint.isActive = true
// MARK: -- DisplayPicture
case let accessory as SessionCell.AccessoryConfig.DisplayPicture:
// Note: We MUST set the 'size' property before triggering the 'update'

@ -12,6 +12,7 @@ public class SessionCell: UITableViewCell {
private var isEditingTitle = false
public private(set) var interactionMode: SessionCell.TextInfo.Interaction = .none
public var lastTouchLocation: UITouch?
private var shouldHighlightTitle: Bool = true
private var originalInputValue: String?
private var titleExtraView: UIView?
@ -610,6 +611,12 @@ public class SessionCell: UITableViewCell {
leadingAccessoryView.setSelected(selected, animated: animated)
trailingAccessoryView.setSelected(selected, animated: animated)
}
public override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
lastTouchLocation = touches.first
}
}
// MARK: - Compose

Loading…
Cancel
Save