156 lines
4.6 KiB
Swift
156 lines
4.6 KiB
Swift
//
|
|
// Copyright 2020 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import Foundation
|
|
|
|
@objc
|
|
public extension TSThread {
|
|
|
|
var isGroupThread: Bool {
|
|
self is TSGroupThread
|
|
}
|
|
|
|
var isNonContactThread: Bool {
|
|
!(self is TSContactThread)
|
|
}
|
|
|
|
var usesSenderKey: Bool {
|
|
self is TSGroupThread || self is TSPrivateStoryThread
|
|
}
|
|
|
|
var isGroupV1Thread: Bool {
|
|
guard let groupThread = self as? TSGroupThread else {
|
|
return false
|
|
}
|
|
return groupThread.groupModel.groupsVersion == .V1
|
|
}
|
|
|
|
var isGroupV2Thread: Bool {
|
|
guard let groupThread = self as? TSGroupThread else {
|
|
return false
|
|
}
|
|
return groupThread.groupModel.groupsVersion == .V2
|
|
}
|
|
|
|
var isReleaseNotesThread: Bool {
|
|
self is TSReleaseNotesThread
|
|
}
|
|
|
|
var groupModelIfGroupThread: TSGroupModel? {
|
|
guard let groupThread = self as? TSGroupThread else {
|
|
return nil
|
|
}
|
|
return groupThread.groupModel
|
|
}
|
|
|
|
var canSendReactionToThread: Bool {
|
|
return !isGroupV1Thread
|
|
}
|
|
|
|
func canSendChatMessagesToThread(ignoreAnnouncementOnly: Bool = false) -> Bool {
|
|
guard !isGroupV1Thread else {
|
|
return false
|
|
}
|
|
if !ignoreAnnouncementOnly {
|
|
guard !isBlockedByAnnouncementOnly else {
|
|
return false
|
|
}
|
|
}
|
|
if let groupThread = self as? TSGroupThread {
|
|
guard groupThread.groupModel.groupMembership.isLocalUserFullMember, !isTerminatedGroup else {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
var isBlockedByAnnouncementOnly: Bool {
|
|
guard let groupThread = self as? TSGroupThread else {
|
|
return false
|
|
}
|
|
guard let groupModel = groupThread.groupModel as? TSGroupModelV2 else {
|
|
return false
|
|
}
|
|
// In "announcement-only" groups, only admins can send messages and start group calls.
|
|
return groupModel.isAnnouncementsOnly && !groupModel.groupMembership.isLocalUserFullMemberAndAdministrator
|
|
}
|
|
|
|
var isAnnouncementOnlyGroupThread: Bool {
|
|
guard let groupThread = self as? TSGroupThread else {
|
|
return false
|
|
}
|
|
guard let groupModel = groupThread.groupModel as? TSGroupModelV2 else {
|
|
return false
|
|
}
|
|
return groupModel.isAnnouncementsOnly
|
|
}
|
|
|
|
func hasPendingMessageRequest(transaction: DBReadTransaction) -> Bool {
|
|
return ThreadFinder().hasPendingMessageRequest(thread: self, transaction: transaction)
|
|
}
|
|
|
|
@nonobjc
|
|
func isSystemContact(contactsManager: ContactManager, tx: DBReadTransaction) -> Bool {
|
|
guard let contactThread = self as? TSContactThread else { return false }
|
|
return contactsManager.fetchSignalAccount(for: contactThread.contactAddress, transaction: tx) != nil
|
|
}
|
|
|
|
// MARK: - Database Hooks
|
|
|
|
internal func _anyDidInsert(tx: DBWriteTransaction) {
|
|
let searchableNameIndexer = DependenciesBridge.shared.searchableNameIndexer
|
|
searchableNameIndexer.insert(self, tx: tx)
|
|
}
|
|
}
|
|
|
|
// MARK: - Drafts
|
|
|
|
extension TSThread {
|
|
|
|
@objc
|
|
public func currentDraft(transaction: DBReadTransaction) -> MessageBody? {
|
|
currentDraft(shouldFetchLatest: true, transaction: transaction)
|
|
}
|
|
|
|
@objc
|
|
public func currentDraft(
|
|
shouldFetchLatest: Bool,
|
|
transaction: DBReadTransaction,
|
|
) -> MessageBody? {
|
|
if shouldFetchLatest {
|
|
guard let thread = TSThread.fetchViaCache(uniqueId: uniqueId, transaction: transaction) else {
|
|
return nil
|
|
}
|
|
return Self.draft(forThread: thread)
|
|
} else {
|
|
return Self.draft(forThread: self)
|
|
}
|
|
}
|
|
|
|
private static func draft(forThread thread: TSThread) -> MessageBody? {
|
|
guard let messageDraft = thread.messageDraft else {
|
|
return nil
|
|
}
|
|
let ranges: MessageBodyRanges = thread.messageDraftBodyRanges ?? .empty
|
|
return MessageBody(text: messageDraft, ranges: ranges)
|
|
}
|
|
|
|
@objc
|
|
public func editTarget(transaction: DBReadTransaction) -> TSOutgoingMessage? {
|
|
guard
|
|
let editTargetTimestamp,
|
|
let localAddress = DependenciesBridge.shared.tsAccountManager.localIdentifiers(tx: transaction)?.aciAddress
|
|
else {
|
|
return nil
|
|
}
|
|
return InteractionFinder.findMessage(
|
|
withTimestamp: editTargetTimestamp,
|
|
threadId: uniqueId,
|
|
author: localAddress,
|
|
transaction: transaction,
|
|
) as? TSOutgoingMessage
|
|
}
|
|
}
|