field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

TeraProductStores.swift (3357B)


      1 import Foundation
      2 
      3 @MainActor
      4 final class TeraProductStores {
      5   let today: TeraTodayStore
      6   let add: TeraAddStore
      7   let search: TeraSearchStore
      8   let me: TeraMeStore
      9   let settings: TeraSettingsStore
     10   let media: TeraMediaStore
     11   let visibility: TeraVisibilityStore
     12   private var generation = TeraSessionGeneration.initial
     13   private var startupTask: Task<Void, Never>?
     14 
     15   init(
     16     runtimeClient: TeraRuntimeClient,
     17     addMedia: (any TeraAddMediaHandling)? = nil
     18   ) {
     19     today = TeraTodayStore(runtimeClient: runtimeClient)
     20     add = TeraAddStore(runtimeClient: runtimeClient, media: addMedia)
     21     search = TeraSearchStore(runtimeClient: runtimeClient)
     22     me = TeraMeStore(runtimeClient: runtimeClient)
     23     settings = TeraSettingsStore(runtimeClient: runtimeClient)
     24     media = TeraMediaStore(runtimeClient: runtimeClient)
     25     visibility = TeraVisibilityStore(runtimeClient: runtimeClient)
     26     visibility.willChange = { [today] in today.invalidateVisibility() }
     27     visibility.didChange = { [today] in await today.reload(refreshProjection: false) }
     28     today.mediaWillChange = { [media] previous, current, context in
     29       media.reconcileVisibility(previous: previous, current: current, context: context)
     30     }
     31     today.scopeWillChange = { [search, me, media] context in
     32       search.stop()
     33       search.configure(context: context)
     34       me.stop()
     35       me.configure(context: context)
     36       media.reset()
     37     }
     38   }
     39 
     40   deinit {
     41     startupTask?.cancel()
     42   }
     43 
     44   func configure(snapshot: TeraRuntimeSnapshot) {
     45     let wasStarting = startupTask != nil
     46     cancelStartup()
     47     if wasStarting {
     48       today.stop()
     49       add.suspend()
     50     }
     51     today.configure(snapshot: snapshot)
     52     add.configure(snapshot: snapshot)
     53     search.stop()
     54     search.configure(context: today.selectedContext)
     55     me.stop()
     56     me.configure(context: today.selectedContext)
     57     settings.configure(snapshot: snapshot)
     58     media.configure(snapshot: snapshot)
     59     visibility.configure(snapshot: snapshot)
     60   }
     61 
     62   func start() {
     63     guard startupTask == nil, generation.isActive, !Task.isCancelled else { return }
     64     generation = generation.invalidated()
     65     guard generation.isActive else { return }
     66     let requested = generation
     67     startupTask = Task { [weak self, today, add] in
     68       async let todayStart: Void = today.start()
     69       async let addStart: Void = add.start()
     70       _ = await (todayStart, addStart)
     71       self?.finishStartup(requested, cancelled: Task.isCancelled)
     72     }
     73   }
     74 
     75   func resume() async {
     76     guard !Task.isCancelled else { return }
     77     start()
     78     guard let task = startupTask else { return }
     79     await withTaskCancellationHandler { await task.value } onCancel: { task.cancel() }
     80   }
     81 
     82   private func finishStartup(_ requested: TeraSessionGeneration, cancelled: Bool) {
     83     guard generation == requested else { return }
     84     startupTask = nil
     85     if cancelled {
     86       today.stop()
     87       add.suspend()
     88     }
     89   }
     90 
     91   func suspend() {
     92     cancelStartup()
     93     today.stop()
     94     add.suspend()
     95     search.stop()
     96     me.stop()
     97     settings.stop()
     98     media.reset()
     99   }
    100 
    101   func stop() {
    102     visibility.stop()
    103     cancelStartup()
    104     today.stop()
    105     add.stop()
    106     search.stop()
    107     me.stop()
    108     settings.stop()
    109     media.reset()
    110   }
    111 
    112   private func cancelStartup() {
    113     generation = generation.invalidated()
    114     startupTask?.cancel()
    115     startupTask = nil
    116   }
    117 }