passepartout-apple/Passepartout/App/Reusable/ReloadingContent.swift

85 lines
2.6 KiB
Swift
Raw Normal View History

2022-04-12 13:09:14 +00:00
//
// ReloadingContent.swift
2022-04-12 13:09:14 +00:00
// Passepartout
//
// Created by Davide De Rosa on 4/4/22.
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import SwiftUI
struct ReloadingContent<T: Equatable, Content: View>: View {
2022-04-12 13:09:14 +00:00
@Environment(\.scenePhase) private var scenePhase
private let elements: [T]
2022-04-12 13:09:14 +00:00
private let equality: ([T], [T]) -> Bool
2022-04-12 13:09:14 +00:00
private let reload: (() -> Void)?
2022-04-12 13:09:14 +00:00
@ViewBuilder private let content: ([T]) -> Content
2022-04-12 13:09:14 +00:00
@State private var localElements: [T] = []
init(
observing elements: [T],
equality: @escaping ([T], [T]) -> Bool = { $0 == $1 },
reload: (() -> Void)? = nil,
@ViewBuilder content: @escaping ([T]) -> Content
) {
self.elements = elements
self.equality = equality
self.reload = reload
self.content = content
// XXX: not sure about this, but if content() is empty .onAppear() will
// never trigger, thus never setting initial elements
//
// BEWARE: localElements will not be automatically bound to changes
// in elements (use a Binding for that), but this is actually intended
_localElements = State(initialValue: elements)
if elements.isEmpty {
reload?()
}
}
2022-04-12 13:09:14 +00:00
var body: some View {
Group {
2022-04-12 13:09:14 +00:00
content(localElements)
// }.onAppear {
// localElements = elements
// if localElements.isEmpty {
// reload?()
// }
2022-04-12 13:09:14 +00:00
}.onChange(of: elements) { newElements in
guard !equality(localElements, newElements) else {
return
}
withAnimation {
localElements = newElements
}
}.onChange(of: scenePhase) {
if $0 == .active {
reload?()
}
}
}
}