diff --git a/ElementX/Sources/Other/CurrentValuePublisher.swift b/ElementX/Sources/Other/CurrentValuePublisher.swift new file mode 100644 index 000000000..495c9c63d --- /dev/null +++ b/ElementX/Sources/Other/CurrentValuePublisher.swift @@ -0,0 +1,45 @@ +// +// Copyright 2023 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine + +/// A wrapper of CurrentValueSubject. +/// The purpose of this type is to remove the possibility to send new values on the underlying subject. +struct CurrentValuePublisher: Publisher { + private let subject: CurrentValueSubject + + init(_ subject: CurrentValueSubject) { + self.subject = subject + } + + init(_ value: Output) { + self.init(CurrentValueSubject(value)) + } + + func receive(subscriber: S) where S: Subscriber, Failure == S.Failure, Output == S.Input { + subject.receive(subscriber: subscriber) + } + + var value: Output { + subject.value + } +} + +extension CurrentValueSubject { + func asCurrentValuePublisher() -> CurrentValuePublisher { + .init(self) + } +} diff --git a/ElementX/Sources/Services/Room/RoomSummary/MockRoomSummaryProvider.swift b/ElementX/Sources/Services/Room/RoomSummary/MockRoomSummaryProvider.swift index 9296c2317..4bf3e24b1 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/MockRoomSummaryProvider.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/MockRoomSummaryProvider.swift @@ -23,9 +23,9 @@ enum MockRoomSummaryProviderState { } class MockRoomSummaryProvider: RoomSummaryProviderProtocol { - let roomListPublisher: CurrentValueSubject<[RoomSummary], Never> - let statePublisher: CurrentValueSubject - let countPublisher: CurrentValueSubject + let roomListPublisher: CurrentValuePublisher<[RoomSummary], Never> + let statePublisher: CurrentValuePublisher + let countPublisher: CurrentValuePublisher convenience init() { self.init(state: .loading) diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift index 8af263704..62382aba3 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift @@ -25,13 +25,25 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { private var cancellables = Set() - let roomListPublisher = CurrentValueSubject<[RoomSummary], Never>([]) - let statePublisher = CurrentValueSubject(.notLoaded) - let countPublisher = CurrentValueSubject(0) + private let roomListSubject = CurrentValueSubject<[RoomSummary], Never>([]) + private let stateSubject = CurrentValueSubject(.notLoaded) + private let countSubject = CurrentValueSubject(0) + + var roomListPublisher: CurrentValuePublisher<[RoomSummary], Never> { + roomListSubject.asCurrentValuePublisher() + } + + var statePublisher: CurrentValuePublisher { + stateSubject.asCurrentValuePublisher() + } + + var countPublisher: CurrentValuePublisher { + countSubject.asCurrentValuePublisher() + } private var rooms: [RoomSummary] = [] { didSet { - roomListPublisher.send(rooms) + roomListSubject.send(rooms) } } @@ -44,15 +56,15 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { buildSummaryForRoomListEntry(roomListEntry) } - roomListPublisher.send(rooms) // didSet not called from initialisers + roomListSubject.send(rooms) // didSet not called from initialisers slidingSyncViewProxy.statePublisher .map(RoomSummaryProviderState.init) - .subscribe(statePublisher) + .subscribe(stateSubject) .store(in: &cancellables) slidingSyncViewProxy.countPublisher - .subscribe(countPublisher) + .subscribe(countSubject) .store(in: &cancellables) slidingSyncViewProxy.diffPublisher diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift index bcc7e75be..083ac7c28 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProviderProtocol.swift @@ -53,13 +53,13 @@ enum RoomSummary: CustomStringConvertible { protocol RoomSummaryProviderProtocol { /// Publishes the currently available room summaries - var roomListPublisher: CurrentValueSubject<[RoomSummary], Never> { get } + var roomListPublisher: CurrentValuePublisher<[RoomSummary], Never> { get } /// Publishes the current state the summary provider is finding itself in - var statePublisher: CurrentValueSubject { get } + var statePublisher: CurrentValuePublisher { get } /// Publishes the total number of rooms - var countPublisher: CurrentValueSubject { get } + var countPublisher: CurrentValuePublisher { get } func updateVisibleRange(_ range: Range, timelineLimit: UInt) } diff --git a/ElementX/Sources/Services/Timeline/MockRoomTimelineProvider.swift b/ElementX/Sources/Services/Timeline/MockRoomTimelineProvider.swift index c746a89b2..bb2dad1ac 100644 --- a/ElementX/Sources/Services/Timeline/MockRoomTimelineProvider.swift +++ b/ElementX/Sources/Services/Timeline/MockRoomTimelineProvider.swift @@ -17,7 +17,7 @@ import Combine struct MockRoomTimelineProvider: RoomTimelineProviderProtocol { - var itemsPublisher = CurrentValueSubject<[TimelineItemProxy], Never>([]) + var itemsPublisher = CurrentValuePublisher<[TimelineItemProxy], Never>([]) private var itemProxies = [TimelineItemProxy]() } diff --git a/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift b/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift index 2c641ea22..93ae724d3 100644 --- a/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift +++ b/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift @@ -31,11 +31,15 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol { private var cancellables = Set() private let serialDispatchQueue: DispatchQueue - let itemsPublisher = CurrentValueSubject<[TimelineItemProxy], Never>([]) + private let itemsSubject = CurrentValueSubject<[TimelineItemProxy], Never>([]) + + var itemsPublisher: CurrentValuePublisher<[TimelineItemProxy], Never> { + itemsSubject.asCurrentValuePublisher() + } private var itemProxies: [TimelineItemProxy] { didSet { - itemsPublisher.send(itemProxies) + itemsSubject.send(itemProxies) } } diff --git a/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift b/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift index 3362c7358..de4c22a4d 100644 --- a/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift +++ b/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift @@ -18,5 +18,5 @@ import Combine import Foundation protocol RoomTimelineProviderProtocol { - var itemsPublisher: CurrentValueSubject<[TimelineItemProxy], Never> { get } + var itemsPublisher: CurrentValuePublisher<[TimelineItemProxy], Never> { get } }