Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Remove RxSwift in favor of combine #671

Merged
merged 5 commits into from
Jun 17, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Packages/ConfCore/ConfCore/RealmCollection+toArray.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import RealmSwift

extension List {
public func toArray() -> [Element] { Array(self) }
}

extension Results {
public func toArray() -> [Element] { Array(self) }
}
49 changes: 23 additions & 26 deletions Packages/ConfCore/ConfCore/Storage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,36 @@
// Copyright © 2017 Guilherme Rambo. All rights reserved.
//

import Combine
import Foundation
import RealmSwift
import RxSwift
import RxRealm
import RxCocoa
import OSLog

public final class Storage: Logging {

public let realmConfig: Realm.Configuration
public let realm: Realm

let disposeBag = DisposeBag()
private var disposeBag: Set<AnyCancellable> = []
public static let log = makeLogger()
private let log = Storage.log

public init(_ realm: Realm) {
self.realmConfig = realm.configuration
self.realm = realm

// This used to be necessary because of CPU usage in the app during script indexing, but it causes a long period of time during indexing where content doesn't reflect what's on the database,
// including for user actions such as favoriting, etc. Tested with the current version of Realm in the app and it doesn't seem to be an issue anymore.
// DistributedNotificationCenter.default().rx.notification(.TranscriptIndexingDidStart).subscribe(onNext: { [unowned self] _ in
// DistributedNotificationCenter.default().publisher(for: .TranscriptIndexingDidStart).sink(receiveValue: { [unowned self] _ in
// os_log("Locking Realm auto-updates until transcript indexing is finished", log: self.log, type: .info)
//
// self.realm.autorefresh = false
// }).disposed(by: disposeBag)
// }).store(in: &disposeBag)
//
// DistributedNotificationCenter.default().rx.notification(.TranscriptIndexingDidStop).subscribe(onNext: { [unowned self] _ in
// DistributedNotificationCenter.default().publisher(for: .TranscriptIndexingDidStop).sink(receiveValue: { [unowned self] _ in
// os_log("Realm auto-updates unlocked", log: self.log, type: .info)
//
// self.realm.autorefresh = true
// }).disposed(by: disposeBag)
// }).store(in: &disposeBag)

deleteOldEventsIfNeeded()
}
Expand Down Expand Up @@ -405,14 +402,14 @@ public final class Storage: Logging {
})
}

public lazy var events: Observable<Results<Event>> = {
public lazy var events: some Publisher<Results<Event>, Error> = {
let eventsSortedByDateDescending = self.realm.objects(Event.self).sorted(byKeyPath: "startDate", ascending: false)

return Observable.collection(from: eventsSortedByDateDescending)
return eventsSortedByDateDescending.collectionPublisher
}()

public lazy var sessionsObservable: Observable<Results<Session>> = {
return Observable.collection(from: self.realm.objects(Session.self))
public lazy var sessionsObservable: some Publisher<Results<Session>, Error> = {
return self.realm.objects(Session.self).collectionPublisher
}()

public var sessions: Results<Session> {
Expand Down Expand Up @@ -442,45 +439,45 @@ public final class Storage: Logging {
})
}

public lazy var eventsObservable: Observable<Results<Event>> = {
public lazy var eventsObservable: some Publisher<Results<Event>, Error> = {
let events = realm.objects(Event.self).sorted(byKeyPath: "startDate", ascending: false)

return Observable.collection(from: events)
return events.collectionPublisher
}()

public lazy var focusesObservable: Observable<Results<Focus>> = {
public lazy var focusesObservable: some Publisher<Results<Focus>, Error> = {
let focuses = realm.objects(Focus.self).sorted(byKeyPath: "name")

return Observable.collection(from: focuses)
return focuses.collectionPublisher
}()

public lazy var tracksObservable: Observable<Results<Track>> = {
public lazy var tracksObservable: some Publisher<Results<Track>, Error> = {
let tracks = self.realm.objects(Track.self).sorted(byKeyPath: "order")

return Observable.collection(from: tracks)
return tracks.collectionPublisher
}()

public lazy var featuredSectionsObservable: Observable<Results<FeaturedSection>> = {
public lazy var featuredSectionsObservable: some Publisher<Results<FeaturedSection>, Error> = {
let predicate = NSPredicate(format: "isPublished = true AND content.@count > 0")
let sections = self.realm.objects(FeaturedSection.self).filter(predicate)

return Observable.collection(from: sections)
return sections.collectionPublisher
}()

public lazy var scheduleObservable: Observable<Results<ScheduleSection>> = {
public lazy var scheduleObservable: some Publisher<Results<ScheduleSection>, Error> = {
let currentEvents = self.realm.objects(Event.self).filter("isCurrent == true")

return Observable.collection(from: currentEvents).map({ $0.first?.identifier }).flatMap { (identifier: String?) -> Observable<Results<ScheduleSection>> in
return currentEvents.collectionPublisher.map({ $0.first?.identifier }).flatMap { (identifier: String?) -> AnyPublisher<Results<ScheduleSection>, Error> in
let sections = self.realm.objects(ScheduleSection.self).filter("eventIdentifier == %@", identifier ?? "").sorted(byKeyPath: "representedDate")

return Observable.collection(from: sections)
return sections.collectionPublisher.eraseToAnyPublisher()
}
}()

public lazy var eventHeroObservable: Observable<EventHero?> = {
public lazy var eventHeroObservable: some Publisher<EventHero?, Error> = {
let hero = self.realm.objects(EventHero.self)

return Observable.collection(from: hero).map { $0.first }
return hero.collectionPublisher.map { $0.first }
}()

public func asset(with remoteURL: URL) -> SessionAsset? {
Expand Down
13 changes: 6 additions & 7 deletions Packages/ConfCore/ConfCore/SyncEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
//

import Foundation
import RxCocoa
import RxSwift
import OSLog
import Combine

extension Notification.Name {
public static let SyncEngineDidSyncSessionsAndSchedule = Notification.Name("SyncEngineDidSyncSessionsAndSchedule")
Expand All @@ -25,7 +24,7 @@ public final class SyncEngine: Logging {

public let userDataSyncEngine: UserDataSyncEngine?

private let disposeBag = DisposeBag()
private var cancellables: Set<AnyCancellable> = []

let transcriptIndexingClient: TranscriptIndexingClient

Expand All @@ -34,8 +33,8 @@ public final class SyncEngine: Logging {
set { transcriptIndexingClient.transcriptLanguage = newValue }
}

public var isIndexingTranscripts: BehaviorRelay<Bool> { transcriptIndexingClient.isIndexing }
public var transcriptIndexingProgress: BehaviorRelay<Float> { transcriptIndexingClient.indexingProgress }
public var isIndexingTranscripts: AnyPublisher<Bool, Never> { transcriptIndexingClient.$isIndexing.eraseToAnyPublisher() }
public var transcriptIndexingProgress: AnyPublisher<Float, Never> { transcriptIndexingClient.$indexingProgress.eraseToAnyPublisher() }

public init(storage: Storage, client: AppleAPIClient, transcriptLanguage: String) {
self.storage = storage
Expand All @@ -52,11 +51,11 @@ public final class SyncEngine: Logging {
self.userDataSyncEngine = nil
}

NotificationCenter.default.rx.notification(.SyncEngineDidSyncSessionsAndSchedule).observe(on: MainScheduler.instance).subscribe(onNext: { [unowned self] _ in
NotificationCenter.default.publisher(for: .SyncEngineDidSyncSessionsAndSchedule).receive(on: DispatchQueue.main).sink(receiveValue: { [unowned self] _ in
self.transcriptIndexingClient.startIndexing(ignoringCache: false)

self.userDataSyncEngine?.start()
}).disposed(by: disposeBag)
}).store(in: &cancellables)
}

public func syncContent() {
Expand Down
12 changes: 5 additions & 7 deletions Packages/ConfCore/ConfCore/TranscriptIndexingClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
//

import Foundation
import RxSwift
import RxCocoa

final class TranscriptIndexingClient: NSObject, TranscriptIndexingClientProtocol, Logging {

Expand Down Expand Up @@ -36,8 +34,8 @@ final class TranscriptIndexingClient: NSObject, TranscriptIndexingClientProtocol
transcriptIndexingConnection.resume()
}

private(set) var isIndexing = BehaviorRelay<Bool>(value: false)
private(set) var indexingProgress = BehaviorRelay<Float>(value: 0)
@Published private(set) var isIndexing = false
@Published private(set) var indexingProgress: Float = 0

private var didRunService = false

Expand Down Expand Up @@ -128,17 +126,17 @@ final class TranscriptIndexingClient: NSObject, TranscriptIndexingClientProtocol
func transcriptIndexingStarted() {
log.debug("\(#function, privacy: .public)")

isIndexing.accept(true)
isIndexing = true
}

func transcriptIndexingProgressDidChange(_ progress: Float) {
indexingProgress.accept(progress)
indexingProgress = progress
}

func transcriptIndexingStopped() {
log.debug("\(#function, privacy: .public)")

isIndexing.accept(false)
isIndexing = false
}

}
8 changes: 4 additions & 4 deletions Packages/ConfCore/ConfCore/TranscriptLanguagesProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//

import Foundation
import RxSwift
import Combine
import OSLog

public final class TranscriptLanguagesProvider: Logging {
Expand All @@ -20,7 +20,7 @@ public final class TranscriptLanguagesProvider: Logging {
self.client = client
}

public private(set) var availableLanguageCodes: BehaviorSubject<[TranscriptLanguage]> = BehaviorSubject(value: [])
public private(set) var availableLanguageCodes = CurrentValueSubject<[TranscriptLanguage], Error>([])

public func fetchAvailableLanguages() {
log.debug("\(#function, privacy: .public)")
Expand All @@ -32,9 +32,9 @@ public final class TranscriptLanguagesProvider: Logging {
case .success(let config):
let languages = config.feeds.keys.compactMap(TranscriptLanguage.init)

self.availableLanguageCodes.on(.next(languages))
self.availableLanguageCodes.value = languages
case .failure(let error):
self.availableLanguageCodes.on(.error(error))
self.availableLanguageCodes.send(completion: .failure(error))
}
}
}
Expand Down
29 changes: 14 additions & 15 deletions Packages/ConfCore/ConfCore/UserDataSyncEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import Foundation
import CloudKit
import CloudKitCodable
import RealmSwift
import RxCocoa
import RxSwift
import Combine
import struct OSLog.Logger

public final class UserDataSyncEngine: Logging {
Expand Down Expand Up @@ -97,7 +96,7 @@ public final class UserDataSyncEngine: Logging {
}
}

private let disposeBag = DisposeBag()
private lazy var cancellables: Set<AnyCancellable> = []

private var canStart = false

Expand All @@ -116,11 +115,11 @@ public final class UserDataSyncEngine: Logging {
// Only start the sync engine if there's an iCloud account available, if availability is not
// determined yet, start the sync engine after the account availability is known and == available

guard isAccountAvailable.value else {
guard isAccountAvailable else {
log.info("iCloud account is not available yet, waiting for availability to start")
isWaitingForAccountAvailabilityToStart = true

isAccountAvailable.asObservable().observe(on: MainScheduler.instance).subscribe(onNext: { [unowned self] available in
$isAccountAvailable.receive(on: DispatchQueue.main).sink(receiveValue: { [unowned self] available in
guard self.isWaitingForAccountAvailabilityToStart else { return }

log.info("iCloud account available = \(String(describing: available), privacy: .public)@")
Expand All @@ -129,7 +128,7 @@ public final class UserDataSyncEngine: Logging {
self.isWaitingForAccountAvailabilityToStart = false
self.start()
}
}).disposed(by: disposeBag)
}).store(in: &cancellables)

return
}
Expand All @@ -146,24 +145,24 @@ public final class UserDataSyncEngine: Logging {
}
}

public private(set) var isStopping = BehaviorRelay<Bool>(value: false)
@Published public private(set) var isStopping = false

public private(set) var isPerformingSyncOperation = BehaviorRelay<Bool>(value: false)
@Published public private(set) var isPerformingSyncOperation = false

public private(set) var isAccountAvailable = BehaviorRelay<Bool>(value: false)
@Published public private(set) var isAccountAvailable = false

public func stop() {
guard isRunning, !isStopping.value else {
guard isRunning, !isStopping else {
self.clearSyncMetadata()
return
}

isStopping.accept(true)
isStopping = true

workQueue.async { [unowned self] in
defer {
DispatchQueue.main.async {
self.isStopping.accept(false)
self.isStopping = false
self.isRunning = false
}
}
Expand All @@ -185,7 +184,7 @@ public final class UserDataSyncEngine: Logging {

private func startObservingSyncOperations() {
cloudQueueObservation = cloudOperationQueue.observe(\.operationCount) { [unowned self] queue, _ in
self.isPerformingSyncOperation.accept(queue.operationCount > 0)
self.isPerformingSyncOperation = queue.operationCount > 0
}
}

Expand Down Expand Up @@ -216,9 +215,9 @@ public final class UserDataSyncEngine: Logging {

switch status {
case .available:
self.isAccountAvailable.accept(true)
self.isAccountAvailable = true
default:
self.isAccountAvailable.accept(false)
self.isAccountAvailable = false
}
}
}
Expand Down
5 changes: 0 additions & 5 deletions Packages/ConfCore/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/bustoutsolutions/siesta", from: "1.5.2"),
.package(url: "https://github.com/realm/realm-swift", from: "10.0.0"),
.package(url: "https://github.com/ReactiveX/RxSwift", from: "6.0.0"),
.package(url: "https://github.com/RxSwiftCommunity/RxRealm", from: "5.0.1"),
.package(url: "https://github.com/insidegui/CloudKitCodable", branch: "spm"),
.package(path: "../Transcripts")
],
Expand All @@ -28,9 +26,6 @@ let package = Package(
"CloudKitCodable",
.product(name: "RealmSwift", package: "realm-swift"),
.product(name: "Siesta", package: "siesta"),
"RxSwift",
.product(name: "RxCocoa", package: "RxSwift"),
"RxRealm",
"Transcripts"
],
path: "ConfCore/")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public final class TranscriptDownloader {
let mismatched = transcriptsByStatus[.etagMismatch, default: []]
let noPreviousEtag = transcriptsByStatus[.noPreviousEtag, default: []]

let cachedEtagMessage = cached.count == 0 ? "none" : noPreviousEtag.map(\.identifier).joined(separator: ", ")
let cachedEtagMessage = cached.count == 0 ? "none" : cached.map(\.identifier).joined(separator: ", ")
let mismatchedMessage = mismatched.count == 0 ? "none" : mismatched.map(\.identifier).joined(separator: ", ")
let noPreviousEtagMessage = noPreviousEtag.count == 0 ? "none" : noPreviousEtag.map(\.identifier).joined(separator: ", ")

Expand Down
Loading