separate indexable query for groups

This commit is contained in:
Michael Kirk 2020-02-14 17:32:06 -07:00
parent e8ef310cd7
commit eb07cda055
4 changed files with 62 additions and 47 deletions

View File

@ -44,7 +44,7 @@ public class ThreadViewModel: NSObject {
self.unreadCount = InteractionFinder(threadUniqueId: thread.uniqueId).unreadCount(transaction: transaction)
self.hasUnreadMessages = unreadCount > 0
self.hasPendingMessageRequest = AnyThreadFinder.hasPendingMessageRequest(thread: thread, transaction: transaction)
self.hasPendingMessageRequest = GRDBThreadFinder.hasPendingMessageRequest(thread: thread, transaction: transaction.unwrapGrdbRead)
}
@objc

View File

@ -406,7 +406,8 @@ NS_ASSUME_NONNULL_BEGIN
__block BOOL hasPendingMessageRequest;
[self.databaseStorage readWithBlock:^(SDSAnyReadTransaction *transaction) {
hasPendingMessageRequest = [AnyThreadFinder hasPendingMessageRequestWithThread:thread transaction:transaction];
hasPendingMessageRequest = [GRDBThreadFinder hasPendingMessageRequestWithThread:thread
transaction:transaction.unwrapGrdbRead];
}];
// If we're creating this thread or we have a pending message request,
@ -424,7 +425,8 @@ NS_ASSUME_NONNULL_BEGIN
{
OWSAssertDebug(thread);
BOOL hasPendingMessageRequest = [AnyThreadFinder hasPendingMessageRequestWithThread:thread transaction:transaction];
BOOL hasPendingMessageRequest = [GRDBThreadFinder hasPendingMessageRequestWithThread:thread
transaction:transaction.unwrapGrdbWrite];
// If we're creating this thread or we have a pending message request,
// any action we trigger should share our profile.

View File

@ -347,11 +347,6 @@ public class InteractionFinder: NSObject, InteractionFinderAdapter {
}
}
@objc
public func possiblyHasIncomingMessages(transaction: GRDBReadTransaction) -> Bool {
return grdbAdapter.possiblyHasIncomingMessages(transaction: transaction)
}
#if DEBUG
@objc
public func enumerateUnstartedExpiringMessages(transaction: SDSAnyReadTransaction, block: @escaping (TSMessage, UnsafeMutablePointer<ObjCBool>) -> Void) {
@ -1040,6 +1035,21 @@ struct GRDBInteractionFinderAdapter: InteractionFinderAdapter {
return try! Bool.fetchOne(transaction.database, sql: sql, arguments: arguments) ?? false
}
func hasGroupUpdateInfoMessage(transaction: GRDBReadTransaction) -> Bool {
let sql = """
SELECT EXISTS(
SELECT 1
FROM \(InteractionRecord.databaseTableName)
WHERE \(interactionColumn: .threadUniqueId) = ?
AND \(interactionColumn: .recordType) = \(SDSRecordType.infoMessage.rawValue)
AND \(interactionColumn: .messageType) = \(TSInfoMessageType.typeGroupUpdate.rawValue)
LIMIT 1
)
"""
let arguments: StatementArguments = [threadUniqueId]
return try! Bool.fetchOne(transaction.database, sql: sql, arguments: arguments)!
}
func possiblyHasIncomingMessages(transaction: GRDBReadTransaction) -> Bool {
// All of these message types could have been triggered by anyone in
// the conversation. So, if one of them exists we have to assume the conversation
@ -1067,15 +1077,11 @@ struct GRDBInteractionFinderAdapter: InteractionFinderAdapter {
FROM \(InteractionRecord.databaseTableName)
WHERE \(interactionColumn: .threadUniqueId) = ?
AND \(interactionColumn: .recordType) IN (\(sqlInteractionTypes))
OR (
\(interactionColumn: .recordType) = \(SDSRecordType.infoMessage.rawValue)
AND \(interactionColumn: .messageType) = \(TSInfoMessageType.typeGroupUpdate.rawValue)
)
LIMIT 1
)
"""
let arguments: StatementArguments = [threadUniqueId]
return try! Bool.fetchOne(transaction.database, sql: sql, arguments: arguments) ?? false
return try! Bool.fetchOne(transaction.database, sql: sql, arguments: arguments)!
}
#if DEBUG

View File

@ -60,35 +60,6 @@ public class AnyThreadFinder: NSObject, ThreadFinder {
return yapAdapter.sortIndex(thread: thread, transaction: yap)
}
}
@objc
public class func hasPendingMessageRequest(thread: TSThread, transaction: ReadTransaction) -> Bool {
// If the feature isn't enabled, do nothing.
guard RemoteConfig.messageRequests else { return false }
// If we're creating the thread, don't show the message request view
guard thread.shouldThreadBeVisible else { return false }
// If the thread is already whitelisted, do nothing. The user has already
// accepted the request for this thread.
guard !SSKEnvironment.shared.profileManager.isThread(
inProfileWhitelist: thread,
transaction: transaction
) else { return false }
let interactionFinder = InteractionFinder(threadUniqueId: thread.uniqueId)
let hasSentMessages = interactionFinder.existsOutgoingMessage(transaction: transaction)
guard !hasSentMessages || FeatureFlags.phoneNumberPrivacy else { return false }
// This thread is likely only visible because of system messages like so-and-so
// is on signal or sync status. Some of the "possibly" incoming messages might
// actually have been triggered by us, but if we sent one of these then the thread
// should be in our profile white list and not make it to this check.
guard interactionFinder.possiblyHasIncomingMessages(transaction: transaction.unwrapGrdbRead) else { return false }
return true
}
}
struct YAPDBThreadFinder: ThreadFinder {
@ -159,13 +130,14 @@ struct YAPDBThreadFinder: ThreadFinder {
}
}
struct GRDBThreadFinder: ThreadFinder {
@objc
public class GRDBThreadFinder: NSObject, ThreadFinder {
typealias ReadTransaction = GRDBReadTransaction
public typealias ReadTransaction = GRDBReadTransaction
static let cn = ThreadRecord.columnName
func visibleThreadCount(isArchived: Bool, transaction: GRDBReadTransaction) throws -> UInt {
public func visibleThreadCount(isArchived: Bool, transaction: GRDBReadTransaction) throws -> UInt {
let sql = """
SELECT COUNT(*)
FROM \(ThreadRecord.databaseTableName)
@ -182,7 +154,8 @@ struct GRDBThreadFinder: ThreadFinder {
return count
}
func enumerateVisibleThreads(isArchived: Bool, transaction: GRDBReadTransaction, block: @escaping (TSThread) -> Void) throws {
@objc
public func enumerateVisibleThreads(isArchived: Bool, transaction: GRDBReadTransaction, block: @escaping (TSThread) -> Void) throws {
let sql = """
SELECT *
FROM \(ThreadRecord.databaseTableName)
@ -197,7 +170,7 @@ struct GRDBThreadFinder: ThreadFinder {
}
}
func sortIndex(thread: TSThread, transaction: GRDBReadTransaction) throws -> UInt? {
public func sortIndex(thread: TSThread, transaction: GRDBReadTransaction) throws -> UInt? {
let sql = """
SELECT sortIndex
FROM (
@ -216,4 +189,38 @@ struct GRDBThreadFinder: ThreadFinder {
let arguments: StatementArguments = [grdbId.intValue]
return try UInt.fetchOne(transaction.database, sql: sql, arguments: arguments)
}
@objc
public class func hasPendingMessageRequest(thread: TSThread, transaction: GRDBReadTransaction) -> Bool {
// If the feature isn't enabled, do nothing.
guard RemoteConfig.messageRequests else { return false }
// If we're creating the thread, don't show the message request view
guard thread.shouldThreadBeVisible else { return false }
// If the thread is already whitelisted, do nothing. The user has already
// accepted the request for this thread.
guard !SSKEnvironment.shared.profileManager.isThread(
inProfileWhitelist: thread,
transaction: transaction.asAnyRead
) else { return false }
let interactionFinder = GRDBInteractionFinderAdapter(threadUniqueId: thread.uniqueId)
let hasSentMessages = interactionFinder.existsOutgoingMessage(transaction: transaction)
guard !hasSentMessages || FeatureFlags.phoneNumberPrivacy else { return false }
if thread.isGroupThread(),
interactionFinder.hasGroupUpdateInfoMessage(transaction: transaction) {
return true
}
// This thread is likely only visible because of system messages like so-and-so
// is on signal or sync status. Some of the "possibly" incoming messages might
// actually have been triggered by us, but if we sent one of these then the thread
// should be in our profile white list and not make it to this check.
guard interactionFinder.possiblyHasIncomingMessages(transaction: transaction) else { return false }
return true
}
}