mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 19:11:45 +00:00
Small tweaks to the Presence feature. (#5918)
This commit is contained in:
@@ -1285,8 +1285,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// State-only (no HTTP): configure the background-refresh sync to carry set_presence=offline so it never
|
// Configure the background-refresh sync to carry set_presence=offline so it doesn't mark the
|
||||||
// reuses the client's foreground sync presence and marks the user online or idle.
|
// user online or idle. Note: If already online/idle then setting offline shouldn't override that.
|
||||||
_ = await userSession.clientProxy.configurePresence(.offline, sendImmediately: false)
|
_ = await userSession.clientProxy.configurePresence(.offline, sendImmediately: false)
|
||||||
|
|
||||||
await resumeClientServices()
|
await resumeClientServices()
|
||||||
|
|||||||
@@ -100,10 +100,9 @@ final class PresenceService {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let clientProxy = clientProxy
|
|
||||||
sendTask = Task { [weak self, clientProxy] in
|
sendTask = Task { [weak self, clientProxy] in
|
||||||
while !Task.isCancelled {
|
while !Task.isCancelled {
|
||||||
guard let presence = await self?.nextPendingPresence() else {
|
guard let presence = self?.nextPendingPresence() else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,10 +112,10 @@ final class PresenceService {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
await self?.finishSending(presence)
|
self?.finishSending(presence)
|
||||||
}
|
}
|
||||||
|
|
||||||
await self?.finishSendTask()
|
self?.finishSendTask()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -175,12 +175,12 @@ struct PresenceServiceTests {
|
|||||||
func newerTransitionWinsWhenAnEarlierSendIsInFlight() async throws {
|
func newerTransitionWinsWhenAnEarlierSendIsInFlight() async throws {
|
||||||
appSettings.sharePresence = true
|
appSettings.sharePresence = true
|
||||||
|
|
||||||
let onlineStarted = PassthroughSubject<Void, Never>()
|
let (onlineStartedStream, onlineStartedContinuation) = AsyncStream<Void>.makeStream()
|
||||||
let gate = AsyncStream<Void>.makeStream()
|
let (resumeOnlineSendStream, resumeOnlineSendContinuation) = AsyncStream<Void>.makeStream()
|
||||||
clientProxy.configurePresenceSendImmediatelyClosure = { [sendsSubject, onlineStarted] presence, sendImmediately in
|
clientProxy.configurePresenceSendImmediatelyClosure = { [sendsSubject] presence, sendImmediately in
|
||||||
if presence == .online {
|
if presence == .online {
|
||||||
onlineStarted.send(())
|
onlineStartedContinuation.yield()
|
||||||
var iterator = gate.stream.makeAsyncIterator()
|
var iterator = resumeOnlineSendStream.makeAsyncIterator()
|
||||||
_ = await iterator.next()
|
_ = await iterator.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,15 +188,15 @@ struct PresenceServiceTests {
|
|||||||
return .success(())
|
return .success(())
|
||||||
}
|
}
|
||||||
|
|
||||||
let onlineStartedDeferred = deferFulfillment(onlineStarted) { _ in true }
|
let onlineStartedDeferred = deferFulfillment(onlineStartedStream) { _ in true }
|
||||||
let service = makeService(initialApplicationState: .active)
|
let service = makeService(initialApplicationState: .active)
|
||||||
try await onlineStartedDeferred.fulfill()
|
try await onlineStartedDeferred.fulfill()
|
||||||
|
|
||||||
let unavailableDeferred = deferFulfillment(sendsSubject) { $0.presence == .unavailable }
|
let unavailableDeferred = deferFulfillment(sendsSubject) { $0.presence == .unavailable }
|
||||||
notificationCenter.post(name: UIApplication.willResignActiveNotification, object: nil)
|
notificationCenter.post(name: UIApplication.willResignActiveNotification, object: nil)
|
||||||
|
|
||||||
gate.continuation.yield()
|
resumeOnlineSendContinuation.yield()
|
||||||
gate.continuation.finish()
|
resumeOnlineSendContinuation.finish()
|
||||||
try await unavailableDeferred.fulfill()
|
try await unavailableDeferred.fulfill()
|
||||||
|
|
||||||
let applied = clientProxy.configurePresenceSendImmediatelyReceivedInvocations.map(\.presence)
|
let applied = clientProxy.configurePresenceSendImmediatelyReceivedInvocations.map(\.presence)
|
||||||
@@ -208,47 +208,29 @@ struct PresenceServiceTests {
|
|||||||
func deinitCancelsPendingSend() async throws {
|
func deinitCancelsPendingSend() async throws {
|
||||||
appSettings.sharePresence = true
|
appSettings.sharePresence = true
|
||||||
|
|
||||||
let onlineStarted = AsyncStream.makeStream(of: Void.self)
|
let (onlineStartedStream, onlineStartedContinuation) = AsyncStream.makeStream(of: Void.self)
|
||||||
let onlineCancelled = AsyncStream.makeStream(of: Void.self)
|
let (onlineFinishedStream, onlineFinishedContinuation) = AsyncStream.makeStream(of: Void.self)
|
||||||
let onlineCompleted = AsyncStream.makeStream(of: Void.self)
|
|
||||||
let gate = AsyncStream.makeStream(of: Void.self)
|
|
||||||
let gateContinuation = gate.continuation
|
|
||||||
let onlineCancelledContinuation = onlineCancelled.continuation
|
|
||||||
let onlineCompletedContinuation = onlineCompleted.continuation
|
|
||||||
|
|
||||||
clientProxy.configurePresenceSendImmediatelyClosure = { presence, _ in
|
clientProxy.configurePresenceSendImmediatelyClosure = { presence, _ in
|
||||||
guard presence == .online else {
|
if presence == .online {
|
||||||
return .success(())
|
onlineStartedContinuation.yield()
|
||||||
|
try? await Task.sleep(for: .seconds(3600)) // Interrupted by the service's deinit cancelling the send task.
|
||||||
|
onlineFinishedContinuation.yield()
|
||||||
}
|
}
|
||||||
|
|
||||||
onlineStarted.continuation.yield()
|
return .success(())
|
||||||
let result: Result<Void, ClientProxyError> = await withTaskCancellationHandler {
|
|
||||||
var iterator = gate.stream.makeAsyncIterator()
|
|
||||||
_ = await iterator.next()
|
|
||||||
return .success(())
|
|
||||||
} onCancel: {
|
|
||||||
gateContinuation.finish()
|
|
||||||
onlineCancelledContinuation.yield()
|
|
||||||
onlineCancelledContinuation.finish()
|
|
||||||
}
|
|
||||||
onlineCompletedContinuation.yield()
|
|
||||||
onlineCompletedContinuation.finish()
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let onlineStartedDeferred = deferFulfillment(onlineStarted.stream) { _ in true }
|
let onlineStartedDeferred = deferFulfillment(onlineStartedStream) { _ in true }
|
||||||
var service: PresenceService? = makeService(initialApplicationState: .active)
|
var service: PresenceService? = makeService(initialApplicationState: .active)
|
||||||
#expect(service != nil)
|
#expect(service != nil)
|
||||||
try await onlineStartedDeferred.fulfill()
|
try await onlineStartedDeferred.fulfill()
|
||||||
|
|
||||||
|
// Queue an unavailable send behind the in-flight online one.
|
||||||
notificationCenter.post(name: UIApplication.willResignActiveNotification, object: nil)
|
notificationCenter.post(name: UIApplication.willResignActiveNotification, object: nil)
|
||||||
|
|
||||||
let onlineCancelledDeferred = deferFulfillment(onlineCancelled.stream) { _ in true }
|
let onlineFinishedDeferred = deferFulfillment(onlineFinishedStream) { _ in true }
|
||||||
let onlineCompletedDeferred = deferFulfillment(onlineCompleted.stream) { _ in true }
|
|
||||||
service = nil
|
service = nil
|
||||||
try await onlineCancelledDeferred.fulfill()
|
try await onlineFinishedDeferred.fulfill()
|
||||||
try await onlineCompletedDeferred.fulfill()
|
|
||||||
|
|
||||||
let applied = clientProxy.configurePresenceSendImmediatelyReceivedInvocations.map(\.presence)
|
let applied = clientProxy.configurePresenceSendImmediatelyReceivedInvocations.map(\.presence)
|
||||||
#expect(applied == [.online], "Expected deinit to cancel the queued unavailable send, got \(applied)")
|
#expect(applied == [.online], "Expected deinit to cancel the queued unavailable send, got \(applied)")
|
||||||
|
|||||||
Reference in New Issue
Block a user