Skip to content
New issue

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

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

Already on GitHub? Sign in 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 all 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