Skip to content

Commit

Permalink
Fix sharing location for other users active location messages
Browse files Browse the repository at this point in the history
  • Loading branch information
nuno-vieira committed Jan 3, 2025
1 parent 1295343 commit 1ab310d
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2024 Stream.io Inc. All rights reserved.
// Copyright © 2025 Stream.io Inc. All rights reserved.
//

import CoreData
Expand Down Expand Up @@ -37,6 +37,9 @@ public class CurrentChatUserController: DataController, DelegateCallable, DataSt
return _basePublishers as? BasePublishers ?? .init(controller: self)
}

/// The observer for the active live location messages.
private var activeLiveLocationMessagesObserver: BackgroundListDatabaseObserver<ChatMessage, MessageDTO>?

/// Used for observing the current user changes in a database.
private lazy var currentUserObserver = createUserObserver()
.onChange { [weak self] change in
Expand All @@ -47,6 +50,22 @@ public class CurrentChatUserController: DataController, DelegateCallable, DataSt
}
$0.currentUserController(self, didChangeCurrentUser: change)
}

/// Only when we have access to the currentUserId is when we should
/// create the observer for the active live location messages.
if self?.activeLiveLocationMessagesObserver == nil {
let observer = self?.createActiveLiveLocationMessagesObserver()
self?.activeLiveLocationMessagesObserver = observer
try? observer?.startObserving()
observer?.onDidChange = { [weak self] _ in
self?.delegateCallback { [weak self] in
guard let self = self else { return }
let messages = Array(observer?.items ?? [])
self.isSharingLiveLocation = !messages.isEmpty
$0.currentUserController(self, didChangeActiveLiveLocationMessages: messages)
}
}
}
}
.onFieldChange(\.unreadCount) { [weak self] change in
self?.delegateCallback { [weak self] in
Expand All @@ -58,20 +77,6 @@ public class CurrentChatUserController: DataController, DelegateCallable, DataSt
}
}

/// The observer for the active live location messages.
private lazy var activeLiveLocationMessagesObserver: BackgroundListDatabaseObserver<ChatMessage, MessageDTO> = {
let observer = createActiveLiveLocationMessagesObserver()
observer.onDidChange = { [weak self] _ in
self?.delegateCallback { [weak self] in
guard let self = self else { return }
let messages = Array(observer.items)
self.isSharingLiveLocation = !messages.isEmpty
$0.currentUserController(self, didChangeActiveLiveLocationMessages: messages)
}
}
return observer
}()

/// A flag to indicate whether the current user is sharing his live location.
private var isSharingLiveLocation = false {
didSet {
Expand Down Expand Up @@ -160,7 +165,6 @@ public class CurrentChatUserController: DataController, DelegateCallable, DataSt

do {
try currentUserObserver.startObserving()
try activeLiveLocationMessagesObserver.startObserving()
state = .localDataFetched
} catch {
log.error("""
Expand Down Expand Up @@ -268,8 +272,11 @@ public extension CurrentChatUserController {
///
/// - Parameter location: The new location to be updated.
func updateLiveLocation(_ location: LocationAttachmentInfo) {
guard let messages = activeLiveLocationMessagesObserver?.items, !messages.isEmpty else {
return
}

locationUpdatesThrottler.execute { [weak self] in
let messages = self?.activeLiveLocationMessagesObserver.items ?? []
for message in messages {
guard let cid = message.cid else { continue }
let messageController = self?.client.messageController(cid: cid, messageId: message.id)
Expand Down Expand Up @@ -442,12 +449,15 @@ private extension CurrentChatUserController {
)
}

func createActiveLiveLocationMessagesObserver() -> BackgroundListDatabaseObserver<ChatMessage, MessageDTO> {
environment.currentUserActiveLiveLocationMessagesObserverBuilder(
func createActiveLiveLocationMessagesObserver() -> BackgroundListDatabaseObserver<ChatMessage, MessageDTO>? {
guard let currentUserId = client.currentUserId else {
return nil
}
return environment.currentUserActiveLiveLocationMessagesObserverBuilder(
client.databaseContainer,
MessageDTO.activeLiveLocationMessagesFetchRequest(
channelId: nil,
currentUserId: client.currentUserId
currentUserId: currentUserId,
channelId: nil
),
{ try $0.asModel() },
NSFetchedResultsController<MessageDTO>.self
Expand Down
20 changes: 9 additions & 11 deletions Sources/StreamChat/Database/DTOs/MessageDTO.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2024 Stream.io Inc. All rights reserved.
// Copyright © 2025 Stream.io Inc. All rights reserved.
//

import CoreData
Expand Down Expand Up @@ -577,9 +577,11 @@ class MessageDTO: NSManagedObject {
return try load(request, context: context)
}

/// Fetches all active location messages in a channel or all channels of the current user.
/// If `channelId` is nil, it will fetch all messages independent of the channel.
static func activeLiveLocationMessagesFetchRequest(
channelId: ChannelId?,
currentUserId: UserId?
currentUserId: UserId,
channelId: ChannelId?
) -> NSFetchRequest<MessageDTO> {
let request = NSFetchRequest<MessageDTO>(entityName: MessageDTO.entityName)
MessageDTO.applyPrefetchingState(to: request)
Expand All @@ -590,11 +592,9 @@ class MessageDTO: NSManagedObject {
ascending: true
)]
var predicates: [NSPredicate] = [
.init(format: "ANY attachments.isActiveLocationAttachment == YES")
.init(format: "ANY attachments.isActiveLocationAttachment == YES"),
.init(format: "user.id == %@", currentUserId)
]
if let currentUserId {
predicates.append(.init(format: "user.id == %@", currentUserId))
}
if let channelId {
predicates.append(.init(format: "channel.cid == %@", channelId.rawValue))
}
Expand All @@ -603,13 +603,11 @@ class MessageDTO: NSManagedObject {
}

static func loadActiveLiveLocationMessages(
currentUserId: UserId,
channelId: ChannelId?,
context: NSManagedObjectContext
) throws -> [MessageDTO] {
let request = activeLiveLocationMessagesFetchRequest(
channelId: channelId,
currentUserId: context.currentUser?.user.id
)
let request = activeLiveLocationMessagesFetchRequest(currentUserId: currentUserId, channelId: channelId)
return try load(request, context: context)
}

Expand Down
6 changes: 5 additions & 1 deletion Sources/StreamChat/Repositories/MessageRepository.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2024 Stream.io Inc. All rights reserved.
// Copyright © 2025 Stream.io Inc. All rights reserved.
//

import CoreData
Expand Down Expand Up @@ -289,7 +289,11 @@ class MessageRepository {
let context = database.backgroundReadOnlyContext
context.perform {
do {
guard let currentUserId = context.currentUser?.user.id else {
return completion(.failure(ClientError.CurrentUserDoesNotExist()))
}
let messages = try MessageDTO.loadActiveLiveLocationMessages(
currentUserId: currentUserId,
channelId: channelId,
context: context
)
Expand Down

0 comments on commit 1ab310d

Please sign in to comment.