Wait for initial profiles (#847)
Show progress view until initial local/remote profiles are fetched. May visually improve later.
This commit is contained in:
parent
49d22e6e67
commit
30ccd58d4a
|
@ -114,11 +114,13 @@ private struct ContainerModifier: ViewModifier {
|
|||
func body(content: Content) -> some View {
|
||||
debugChanges()
|
||||
return content
|
||||
.themeEmptyContent(if: !profileManager.hasProfiles, message: Strings.Views.Profiles.Folders.noProfiles)
|
||||
.themeProgress(if: !profileManager.isReady)
|
||||
.themeEmptyContent(if: profileManager.isReady && !profileManager.hasProfiles, message: Strings.Views.Profiles.Folders.noProfiles)
|
||||
.searchable(text: $search)
|
||||
.onChange(of: search) {
|
||||
profileManager.search(byName: $0)
|
||||
}
|
||||
.themeAnimation(on: profileManager.isReady, category: .profiles)
|
||||
.themeAnimation(on: profileManager.headers, category: .profiles)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,12 +29,20 @@ import PassepartoutKit
|
|||
|
||||
@MainActor
|
||||
public final class ProfileManager: ObservableObject {
|
||||
private enum Observer: CaseIterable {
|
||||
case local
|
||||
|
||||
case remote
|
||||
}
|
||||
|
||||
public enum Event {
|
||||
case save(Profile)
|
||||
|
||||
case remove([Profile.ID])
|
||||
}
|
||||
|
||||
// MARK: Dependencies
|
||||
|
||||
private let repository: ProfileRepository
|
||||
|
||||
private let backupRepository: ProfileRepository?
|
||||
|
@ -47,6 +55,8 @@ public final class ProfileManager: ObservableObject {
|
|||
|
||||
private let processor: ProfileProcessor?
|
||||
|
||||
// MARK: State
|
||||
|
||||
@Published
|
||||
private var profiles: [Profile]
|
||||
|
||||
|
@ -56,10 +66,19 @@ public final class ProfileManager: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
private var allRemoteProfiles: [Profile.ID: Profile]
|
||||
|
||||
@Published
|
||||
public private(set) var isRemoteImportingEnabled: Bool
|
||||
|
||||
private var allRemoteProfiles: [Profile.ID: Profile]
|
||||
public var isReady: Bool {
|
||||
waitingObservers.isEmpty
|
||||
}
|
||||
|
||||
@Published
|
||||
private var waitingObservers: Set<Observer>
|
||||
|
||||
// MARK: Publishers
|
||||
|
||||
public let didChange: PassthroughSubject<Event, Never>
|
||||
|
||||
|
@ -78,15 +97,17 @@ public final class ProfileManager: ObservableObject {
|
|||
}
|
||||
mirrorsRemoteRepository = false
|
||||
processor = nil
|
||||
|
||||
self.profiles = []
|
||||
allProfiles = profiles.reduce(into: [:]) {
|
||||
$0[$1.id] = $1
|
||||
}
|
||||
allRemoteProfiles = [:]
|
||||
isRemoteImportingEnabled = false
|
||||
waitingObservers = []
|
||||
|
||||
didChange = PassthroughSubject()
|
||||
searchSubject = CurrentValueSubject("")
|
||||
isRemoteImportingEnabled = false
|
||||
subscriptions = []
|
||||
remoteSubscriptions = []
|
||||
}
|
||||
|
@ -104,13 +125,19 @@ public final class ProfileManager: ObservableObject {
|
|||
self.remoteRepositoryBlock = remoteRepositoryBlock
|
||||
self.mirrorsRemoteRepository = mirrorsRemoteRepository
|
||||
self.processor = processor
|
||||
|
||||
profiles = []
|
||||
allProfiles = [:]
|
||||
allRemoteProfiles = [:]
|
||||
isRemoteImportingEnabled = false
|
||||
if remoteRepositoryBlock != nil {
|
||||
waitingObservers = [.local, .remote]
|
||||
} else {
|
||||
waitingObservers = [.local]
|
||||
}
|
||||
|
||||
didChange = PassthroughSubject()
|
||||
searchSubject = CurrentValueSubject("")
|
||||
isRemoteImportingEnabled = false
|
||||
subscriptions = []
|
||||
remoteSubscriptions = []
|
||||
}
|
||||
|
@ -323,10 +350,10 @@ extension ProfileManager {
|
|||
self.isRemoteImportingEnabled = isRemoteImportingEnabled
|
||||
remoteSubscriptions.removeAll()
|
||||
|
||||
remoteRepository = remoteRepositoryBlock(isRemoteImportingEnabled)
|
||||
if let initialProfiles = try await remoteRepository?.fetchProfiles() {
|
||||
let newRepository = remoteRepositoryBlock(isRemoteImportingEnabled)
|
||||
let initialProfiles = try await newRepository.fetchProfiles()
|
||||
reloadRemoteProfiles(initialProfiles, importing: false)
|
||||
}
|
||||
remoteRepository = newRepository
|
||||
|
||||
remoteRepository?
|
||||
.profilesPublisher
|
||||
|
@ -345,7 +372,9 @@ private extension ProfileManager {
|
|||
allProfiles = result.reduce(into: [:]) {
|
||||
$0[$1.id] = $1
|
||||
}
|
||||
// objectWillChange implicit from updating profiles in didSet
|
||||
if waitingObservers.contains(.local) {
|
||||
waitingObservers.remove(.local)
|
||||
}
|
||||
|
||||
// should not be imported at all, but you never know
|
||||
if let processor {
|
||||
|
@ -369,7 +398,9 @@ private extension ProfileManager {
|
|||
allRemoteProfiles = result.reduce(into: [:]) {
|
||||
$0[$1.id] = $1
|
||||
}
|
||||
objectWillChange.send()
|
||||
if waitingObservers.contains(.remote) {
|
||||
waitingObservers.remove(.remote)
|
||||
}
|
||||
|
||||
guard importing else {
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue