172 lines
5.0 KiB
Swift
172 lines
5.0 KiB
Swift
//
|
|
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import PromiseKit
|
|
|
|
@objc
|
|
protocol GroupViewHelperDelegate: class {
|
|
func groupViewHelperDidUpdateGroup()
|
|
|
|
var currentGroupModel: TSGroupModel? { get }
|
|
|
|
var fromViewController: UIViewController? { get }
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
@objc
|
|
class GroupViewHelper: NSObject {
|
|
|
|
// MARK: - Dependencies
|
|
|
|
var tsAccountManager: TSAccountManager {
|
|
return .sharedInstance()
|
|
}
|
|
|
|
var contactsManager: OWSContactsManager {
|
|
return Environment.shared.contactsManager
|
|
}
|
|
|
|
var blockingManager: OWSBlockingManager {
|
|
return .shared()
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
@objc
|
|
weak var delegate: GroupViewHelperDelegate?
|
|
|
|
let threadViewModel: ThreadViewModel
|
|
|
|
var thread: TSThread {
|
|
return threadViewModel.threadRecord
|
|
}
|
|
|
|
var fromViewController: UIViewController? {
|
|
return delegate?.fromViewController
|
|
}
|
|
|
|
@objc
|
|
init(threadViewModel: ThreadViewModel) {
|
|
self.threadViewModel = threadViewModel
|
|
}
|
|
|
|
// MARK: - Accessors
|
|
|
|
// Don't use this method directly;
|
|
// Use canEditConversationAttributes or canEditConversationMembership instead.
|
|
private func canLocalUserEditConversation(v2AccessTypeBlock: (GroupAccess) -> GroupV2Access) -> Bool {
|
|
if threadViewModel.hasPendingMessageRequest {
|
|
return false
|
|
}
|
|
guard isLocalUserFullMemberOfGroup else {
|
|
return false
|
|
}
|
|
guard let groupThread = thread as? TSGroupThread else {
|
|
// Both users can edit contact threads.
|
|
return true
|
|
}
|
|
guard !blockingManager.isThreadBlocked(groupThread) else {
|
|
return false
|
|
}
|
|
guard let groupModelV2 = groupThread.groupModel as? TSGroupModelV2 else {
|
|
// All users can edit v1 groups.
|
|
return true
|
|
}
|
|
guard let localAddress = tsAccountManager.localAddress else {
|
|
owsFailDebug("Missing localAddress.")
|
|
return false
|
|
}
|
|
// Use the block to pick the access type: attributes or members?
|
|
let access = v2AccessTypeBlock(groupModelV2.access)
|
|
switch access {
|
|
case .unknown:
|
|
owsFailDebug("Unknown access.")
|
|
return false
|
|
case .unsatisfiable:
|
|
owsFailDebug("Invalid access.")
|
|
return false
|
|
case .any:
|
|
return true
|
|
case .member:
|
|
return groupModelV2.groupMembership.isFullMember(localAddress)
|
|
case .administrator:
|
|
return (groupModelV2.groupMembership.isFullMemberAndAdministrator(localAddress))
|
|
}
|
|
}
|
|
|
|
// Can local user edit conversation attributes:
|
|
//
|
|
// * DM state
|
|
// * Group title (if group)
|
|
// * Group avatar (if group)
|
|
var canEditConversationAttributes: Bool {
|
|
return canLocalUserEditConversation { groupAccess in
|
|
return groupAccess.attributes
|
|
}
|
|
}
|
|
|
|
// Can local user edit group membership.
|
|
var canEditConversationMembership: Bool {
|
|
return canLocalUserEditConversation { groupAccess in
|
|
return groupAccess.members
|
|
}
|
|
}
|
|
|
|
// Can local user edit group access.
|
|
var canEditConversationAccess: Bool {
|
|
if threadViewModel.hasPendingMessageRequest {
|
|
return false
|
|
}
|
|
guard isLocalUserFullMemberOfGroup else {
|
|
return false
|
|
}
|
|
guard let groupThread = thread as? TSGroupThread else {
|
|
// Contact threads don't use access.
|
|
return false
|
|
}
|
|
guard let groupModelV2 = groupThread.groupModel as? TSGroupModelV2 else {
|
|
// v1 groups don't use access.
|
|
return false
|
|
}
|
|
guard let localAddress = tsAccountManager.localAddress else {
|
|
owsFailDebug("Missing localAddress.")
|
|
return false
|
|
}
|
|
return groupModelV2.groupMembership.isFullMemberAndAdministrator(localAddress)
|
|
}
|
|
|
|
var canRevokePendingInvites: Bool {
|
|
guard let groupThread = thread as? TSGroupThread else {
|
|
return false
|
|
}
|
|
guard let localAddress = tsAccountManager.localAddress else {
|
|
owsFailDebug("Missing localAddress.")
|
|
return false
|
|
}
|
|
let groupMembership = groupThread.groupModel.groupMembership
|
|
return (!threadViewModel.hasPendingMessageRequest &&
|
|
groupMembership.isFullMemberAndAdministrator(localAddress))
|
|
}
|
|
|
|
var canResendInvites: Bool {
|
|
return (!threadViewModel.hasPendingMessageRequest && isLocalUserFullMemberOfGroup)
|
|
}
|
|
|
|
var isLocalUserFullMemberOfGroup: Bool {
|
|
guard let groupThread = thread as? TSGroupThread else {
|
|
return true
|
|
}
|
|
return groupThread.isLocalUserFullMemberOfGroup
|
|
}
|
|
|
|
var isLocalUserFullOrInvitedMemberOfGroup: Bool {
|
|
guard let groupThread = thread as? TSGroupThread else {
|
|
return true
|
|
}
|
|
return groupThread.isLocalUserFullOrInvitedMemberOfGroup
|
|
}
|
|
}
|