|
|
|
@ -53,27 +53,65 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|
|
|
|
// MARK: - Initialization
|
|
|
|
|
|
|
|
|
|
init(threadId: String, threadVariant: SessionThread.Variant, focusedInteractionId: Int64?) {
|
|
|
|
|
// If we have a specified 'focusedInteractionId' then use that, otherwise retrieve the oldest
|
|
|
|
|
// unread interaction and start focused around that one
|
|
|
|
|
let targetInteractionId: Int64? = {
|
|
|
|
|
if let focusedInteractionId: Int64 = focusedInteractionId { return focusedInteractionId }
|
|
|
|
|
typealias InitialData = (
|
|
|
|
|
targetInteractionId: Int64?,
|
|
|
|
|
currentUserIsClosedGroupMember: Bool?,
|
|
|
|
|
openGroupPermissions: OpenGroup.Permissions?,
|
|
|
|
|
blindedKey: String?
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
let initialData: InitialData? = Storage.shared.read { db -> InitialData in
|
|
|
|
|
let interaction: TypedTableAlias<Interaction> = TypedTableAlias()
|
|
|
|
|
let groupMember: TypedTableAlias<GroupMember> = TypedTableAlias()
|
|
|
|
|
|
|
|
|
|
return Storage.shared.read { db in
|
|
|
|
|
let interaction: TypedTableAlias<Interaction> = TypedTableAlias()
|
|
|
|
|
|
|
|
|
|
return try Interaction
|
|
|
|
|
// If we have a specified 'focusedInteractionId' then use that, otherwise retrieve the oldest
|
|
|
|
|
// unread interaction and start focused around that one
|
|
|
|
|
let targetInteractionId: Int64? = (focusedInteractionId != nil ? focusedInteractionId :
|
|
|
|
|
try Interaction
|
|
|
|
|
.select(.id)
|
|
|
|
|
.filter(interaction[.wasRead] == false)
|
|
|
|
|
.filter(interaction[.threadId] == threadId)
|
|
|
|
|
.order(interaction[.timestampMs].asc)
|
|
|
|
|
.asRequest(of: Int64.self)
|
|
|
|
|
.fetchOne(db)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
)
|
|
|
|
|
let currentUserIsClosedGroupMember: Bool? = (threadVariant != .closedGroup ? nil :
|
|
|
|
|
try GroupMember
|
|
|
|
|
.filter(groupMember[.groupId] == threadId)
|
|
|
|
|
.filter(groupMember[.profileId] == getUserHexEncodedPublicKey(db))
|
|
|
|
|
.filter(groupMember[.role] == GroupMember.Role.standard)
|
|
|
|
|
.isNotEmpty(db)
|
|
|
|
|
)
|
|
|
|
|
let openGroupPermissions: OpenGroup.Permissions? = (threadVariant != .openGroup ? nil :
|
|
|
|
|
try OpenGroup
|
|
|
|
|
.filter(id: threadId)
|
|
|
|
|
.select(.permissions)
|
|
|
|
|
.asRequest(of: OpenGroup.Permissions.self)
|
|
|
|
|
.fetchOne(db)
|
|
|
|
|
)
|
|
|
|
|
let blindedKey: String? = SessionThread.getUserHexEncodedBlindedKey(
|
|
|
|
|
db,
|
|
|
|
|
threadId: threadId,
|
|
|
|
|
threadVariant: threadVariant
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
targetInteractionId,
|
|
|
|
|
currentUserIsClosedGroupMember,
|
|
|
|
|
openGroupPermissions,
|
|
|
|
|
blindedKey
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.threadId = threadId
|
|
|
|
|
self.initialThreadVariant = threadVariant
|
|
|
|
|
self.focusedInteractionId = targetInteractionId
|
|
|
|
|
self.focusedInteractionId = initialData?.targetInteractionId
|
|
|
|
|
self.threadData = SessionThreadViewModel(
|
|
|
|
|
threadId: threadId,
|
|
|
|
|
threadVariant: threadVariant,
|
|
|
|
|
currentUserIsClosedGroupMember: initialData?.currentUserIsClosedGroupMember,
|
|
|
|
|
openGroupPermissions: initialData?.openGroupPermissions
|
|
|
|
|
).populatingCurrentUserBlindedKey(currentUserBlindedPublicKeyForThisThread: initialData?.blindedKey)
|
|
|
|
|
self.pagedDataObserver = nil
|
|
|
|
|
|
|
|
|
|
// Note: Since this references self we need to finish initializing before setting it, we
|
|
|
|
@ -93,7 +131,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|
|
|
|
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
|
|
|
|
|
// If we don't have a `initialFocusedId` then default to `.pageBefore` (it'll query
|
|
|
|
|
// from a `0` offset)
|
|
|
|
|
guard let initialFocusedId: Int64 = targetInteractionId else {
|
|
|
|
|
guard let initialFocusedId: Int64 = initialData?.targetInteractionId else {
|
|
|
|
|
self?.pagedDataObserver?.load(.pageBefore)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
@ -105,21 +143,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|
|
|
|
// MARK: - Thread Data
|
|
|
|
|
|
|
|
|
|
/// This value is the current state of the view
|
|
|
|
|
public private(set) lazy var threadData: SessionThreadViewModel = SessionThreadViewModel(
|
|
|
|
|
threadId: self.threadId,
|
|
|
|
|
threadVariant: self.initialThreadVariant,
|
|
|
|
|
currentUserIsClosedGroupMember: (self.initialThreadVariant != .closedGroup ?
|
|
|
|
|
nil :
|
|
|
|
|
Storage.shared.read { db in
|
|
|
|
|
try GroupMember
|
|
|
|
|
.filter(GroupMember.Columns.groupId == self.threadId)
|
|
|
|
|
.filter(GroupMember.Columns.profileId == getUserHexEncodedPublicKey(db))
|
|
|
|
|
.filter(GroupMember.Columns.role == GroupMember.Role.standard)
|
|
|
|
|
.isNotEmpty(db)
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
.populatingCurrentUserBlindedKey()
|
|
|
|
|
public private(set) var threadData: SessionThreadViewModel
|
|
|
|
|
|
|
|
|
|
/// This is all the data the screen needs to populate itself, please see the following link for tips to help optimise
|
|
|
|
|
/// performance https://github.com/groue/GRDB.swift#valueobservation-performance
|
|
|
|
|