SDWebImageSwiftUI/SDWebImageSwiftUI/Classes/Indicator/Indicator.swift

95 lines
3.4 KiB
Swift

/*
* This file is part of the SDWebImage package.
* (c) DreamPiggy <lizhuoli1126@126.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import Foundation
import SwiftUI
/// A type to build the indicator
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct Indicator<T> where T : View {
var content: (Binding<Bool>, Binding<Double>) -> T
/// Create a indicator with builder
/// - Parameter builder: A builder to build indicator
/// - Parameter isAnimating: A Binding to control the animation. If image is during loading, the value is true, else (like start loading) the value is false.
/// - Parameter progress: A Binding to control the progress during loading. Value between [0.0, 1.0]. If no progress can be reported, the value is 0.
/// Associate a indicator when loading image with url
public init(@ViewBuilder content: @escaping (_ isAnimating: Binding<Bool>, _ progress: Binding<Double>) -> T) {
self.content = content
}
}
/// A protocol to report indicator progress
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol IndicatorReportable : ObservableObject {
/// whether indicator is loading or not
var isLoading: Bool { get set }
/// indicator progress, should only be used for indicator binding, value between [0.0, 1.0]
var progress: Double { get set }
}
/// A implementation detail View Modifier with indicator
/// SwiftUI View Modifier construced by using a internal View type which modify the `body`
/// It use type system to represent the view hierarchy, and Swift `some View` syntax to hide the type detail for users
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct IndicatorViewModifier<T, V> : ViewModifier where T : View, V : IndicatorReportable {
/// The progress reporter
@ObservedObject var reporter: V
/// The indicator
var indicator: Indicator<T>
public func body(content: Content) -> some View {
ZStack {
content
if reporter.isLoading {
indicator.content($reporter.isLoading, $reporter.progress)
}
}
}
}
#if os(macOS) || os(iOS) || os(tvOS)
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Indicator where T == ActivityIndicator {
/// Activity Indicator
public static var activity: Indicator {
Indicator { isAnimating, _ in
ActivityIndicator(isAnimating)
}
}
/// Activity Indicator with style
/// - Parameter style: style
public static func activity(style: ActivityIndicator.Style) -> Indicator {
Indicator { isAnimating, _ in
ActivityIndicator(isAnimating, style: style)
}
}
}
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Indicator where T == ProgressIndicator {
/// Progress Indicator
public static var progress: Indicator {
Indicator { isAnimating, progress in
ProgressIndicator(isAnimating, progress: progress)
}
}
/// Progress Indicator with style
/// - Parameter style: style
public static func progress(style: ProgressIndicator.Style) -> Indicator {
Indicator { isAnimating, progress in
ProgressIndicator(isAnimating, progress: progress, style: style)
}
}
}
#endif