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

feat: 🎸 [JIRA:HCPSDKFIORIUIKIT-2806] Processing Indicator #906

Merged
merged 2 commits into from
Nov 27, 2024
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
4 changes: 4 additions & 0 deletions Apps/Examples/Examples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
3CDD6ECD2CE4277300DDAE7D /* CheckoutIndicatorModalExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CDD6ECC2CE4277300DDAE7D /* CheckoutIndicatorModalExample.swift */; };
55598FAD2CDDB4F6007CFFBB /* ValuePickerExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55598FAC2CDDB4F6007CFFBB /* ValuePickerExample.swift */; };
6432FFA02C5164F8008ECE89 /* SegmentedControlExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6432FF9F2C5164F8008ECE89 /* SegmentedControlExample.swift */; };
6439F5142CEE892200EF1B42 /* ProcessingIndicatorExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6439F5132CEE892200EF1B42 /* ProcessingIndicatorExample.swift */; };
64905D072C6D13E20062AAD4 /* SwitchExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64905D062C6D13E20062AAD4 /* SwitchExample.swift */; };
64905D092C7693970062AAD4 /* DateTimePickerExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64905D082C7693970062AAD4 /* DateTimePickerExample.swift */; };
649C7F482CE531C8007B78A7 /* ProgressIndicatorExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649C7F472CE531C5007B78A7 /* ProgressIndicatorExample.swift */; };
Expand Down Expand Up @@ -251,6 +252,7 @@
3CDD6ECC2CE4277300DDAE7D /* CheckoutIndicatorModalExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckoutIndicatorModalExample.swift; sourceTree = "<group>"; };
55598FAC2CDDB4F6007CFFBB /* ValuePickerExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValuePickerExample.swift; sourceTree = "<group>"; };
6432FF9F2C5164F8008ECE89 /* SegmentedControlExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedControlExample.swift; sourceTree = "<group>"; };
6439F5132CEE892200EF1B42 /* ProcessingIndicatorExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessingIndicatorExample.swift; sourceTree = "<group>"; };
64905D062C6D13E20062AAD4 /* SwitchExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchExample.swift; sourceTree = "<group>"; };
64905D082C7693970062AAD4 /* DateTimePickerExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTimePickerExample.swift; sourceTree = "<group>"; };
649C7F472CE531C5007B78A7 /* ProgressIndicatorExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressIndicatorExample.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -752,6 +754,7 @@
649C7F472CE531C5007B78A7 /* ProgressIndicatorExample.swift */,
99658F872B7C359D0026A743 /* LinearProgressIndicatorExample.swift */,
A65036932CC6365C0093086A /* LoadingIndicatorExample.swift */,
6439F5132CEE892200EF1B42 /* ProcessingIndicatorExample.swift */,
);
path = Indicator;
sourceTree = "<group>";
Expand Down Expand Up @@ -1250,6 +1253,7 @@
6D6E866F2C539CDE00EDB6F4 /* InPlaceLoadingFlexibleButtonExample.swift in Sources */,
B1F384322C815A540090A858 /* AvatarStackExample.swift in Sources */,
B1BCB6E12C2EB362008AC070 /* ProfileHeaderStaticExample.swift in Sources */,
6439F5142CEE892200EF1B42 /* ProcessingIndicatorExample.swift in Sources */,
C1C764882A818BEC00BCB0F7 /* SortFilterExample.swift in Sources */,
64905D072C6D13E20062AAD4 /* SwitchExample.swift in Sources */,
B1F6FC302B22BDDA005190F9 /* ToolbarView.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,12 @@ struct CoreContentView: View {
{
Text("Progress Indicator")
}

NavigationLink(
destination: ProcessingIndicatorExample())
{
Text("Processing Indicator")
}
}

Section(header: Text("Navigation Bar")) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import FioriSwiftUICore
import FioriThemeManager
import SwiftUI

struct Blur: UIViewRepresentable {
var style: UIBlurEffect.Style = .extraLight
func makeUIView(context: Context) -> UIVisualEffectView {
let view = UIVisualEffectView(effect: UIBlurEffect(style: .extraLight))
DispatchQueue.main.async {
view.superview?.superview?.backgroundColor = .clear
}
return view
}

func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
uiView.effect = UIBlurEffect(style: self.style)
}
}

struct ProcessingIndicatorExample: View {
@State var labelText: String = "Processing"
@State var showModalIndicator: Bool = false
@State var showInContainer: Bool = false

var body: some View {
VStack {
Spacer()
Button("Show modal indicator", action: {
self.showModalIndicator.toggle()
})
Button("Show/hide in container", action: {
self.showInContainer.toggle()
})
TextFieldFormView(title: "Set label", text: self.$labelText).padding()
ProcessingIndicator(optionalTitle: AttributedString(self.labelText))
Spacer()
if self.showInContainer {
Image("rw")
.overlay(ProcessingIndicator()
.frame(maxWidth: 130, maxHeight: 130)
.background(Color.white.opacity(0.7))
)
} else {
Image("rw")
}
Spacer()
}
.padding()
.fullScreenCover(isPresented: self.$showModalIndicator, content: {
VStack {
ProcessingIndicator(optionalTitle: AttributedString(self.labelText))
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.clear)
Button("Dismiss", action: {
self.showModalIndicator.toggle()
})
}
.background(Blur())
})
}
}

struct ProcessingIndicatorExample_Previews: PreviewProvider {
static var previews: some View {
ProcessingIndicatorExample()
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ We plan to progressively bring more Fiori UI components into this module in the
| Calendar | :x: |
| Search To Select | :x: |
| Progress Indicator | :white_check_mark: |
| Processing Indicator | :x: |
| Processing Indicator | :white_check_mark: |
| Checkout Indicator | :white_check_mark: |
| Loading Indicator | :white_check_mark: |
| Feedback Screen | :x: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -717,3 +717,12 @@ protocol _ValuePickerComponent: _TitleComponent, _ValueLabelComponent, _Mandator
/// ```
// sourcery: CompositeComponent
protocol _ProgressIndicatorComponent: _ProgressIndicatorProtocol {}

/// `ProcessingIndicator` provides a circular indeterminate indicator with an optional title below the indicator.
///
/// ## Usage
/// ```swift
/// ProcessingIndicator(optionalTitle: "Processing")
/// ```
// sourcery: CompositeComponent
protocol _ProcessingIndicatorComponent: _OptionalTitleComponent {}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File Length Violation: File should contain 700 lines or less: currently contains 728 (file_length)

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import FioriThemeManager

// Generated using Sourcery 2.1.7 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
import Foundation
import SwiftUI

// Base Layout style
public struct ProcessingIndicatorBaseStyle: ProcessingIndicatorStyle {
struct ProcessingIndicatorStyle: ProgressIndicatorStyle {
func makeBody(_ configuration: ProgressIndicatorConfiguration) -> some View {
ProgressIndicator(configuration)
.frame(width: 56, height: 56)
}
}

public func makeBody(_ configuration: ProcessingIndicatorConfiguration) -> some View {
VStack {
ProgressIndicator(progress: Binding<Double>.constant(0.0))
.progressIndicatorStyle(ProcessingIndicatorStyle())
.progressIndicatorStyle(.processing)
if !configuration.optionalTitle.isEmpty {
configuration.optionalTitle
.offset(y: 15)
}
}.padding()
}
}

// Default fiori styles
extension ProcessingIndicatorFioriStyle {
struct ContentFioriStyle: ProcessingIndicatorStyle {
func makeBody(_ configuration: ProcessingIndicatorConfiguration) -> some View {
ProcessingIndicator(configuration)
}
}

struct OptionalTitleFioriStyle: OptionalTitleStyle {
let processingIndicatorConfiguration: ProcessingIndicatorConfiguration

func makeBody(_ configuration: OptionalTitleConfiguration) -> some View {
OptionalTitle(configuration)
.foregroundStyle(Color.preferredColor(.primaryLabel))
.font(.fiori(fixedSize: 12))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Generated using Sourcery 2.1.7 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
import Foundation
import SwiftUI

/// `ProcessingIndicator` provides a circular indeterminate indicator with an optional title below the indicator.
///
/// ## Usage
/// ```swift
/// ProcessingIndicator(optionalTitle: "Processing")
/// ```
public struct ProcessingIndicator {
let optionalTitle: any View

@Environment(\.processingIndicatorStyle) var style

fileprivate var _shouldApplyDefaultStyle = true

public init(@ViewBuilder optionalTitle: () -> any View = { EmptyView() }) {
self.optionalTitle = OptionalTitle(optionalTitle: optionalTitle)
}
}

public extension ProcessingIndicator {
init(optionalTitle: AttributedString?) {
self.init(optionalTitle: { OptionalText(optionalTitle) })
}
}

public extension ProcessingIndicator {
init(_ configuration: ProcessingIndicatorConfiguration) {
self.init(configuration, shouldApplyDefaultStyle: false)
}

internal init(_ configuration: ProcessingIndicatorConfiguration, shouldApplyDefaultStyle: Bool) {
self.optionalTitle = configuration.optionalTitle
self._shouldApplyDefaultStyle = shouldApplyDefaultStyle
}
}

extension ProcessingIndicator: View {
public var body: some View {
if self._shouldApplyDefaultStyle {
self.defaultStyle()
} else {
self.style.resolve(configuration: .init(optionalTitle: .init(self.optionalTitle))).typeErased
.transformEnvironment(\.processingIndicatorStyleStack) { stack in
if !stack.isEmpty {
stack.removeLast()
}
}
}
}
}

private extension ProcessingIndicator {
func shouldApplyDefaultStyle(_ bool: Bool) -> some View {
var s = self
s._shouldApplyDefaultStyle = bool
return s
}

func defaultStyle() -> some View {
ProcessingIndicator(.init(optionalTitle: .init(self.optionalTitle)))
.shouldApplyDefaultStyle(false)
.processingIndicatorStyle(ProcessingIndicatorFioriStyle.ContentFioriStyle())
.typeErased
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Generated using Sourcery 2.1.7 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
import Foundation
import SwiftUI

public protocol ProcessingIndicatorStyle: DynamicProperty {
associatedtype Body: View

func makeBody(_ configuration: ProcessingIndicatorConfiguration) -> Body
}

struct AnyProcessingIndicatorStyle: ProcessingIndicatorStyle {
let content: (ProcessingIndicatorConfiguration) -> any View

init(@ViewBuilder _ content: @escaping (ProcessingIndicatorConfiguration) -> any View) {
self.content = content
}

public func makeBody(_ configuration: ProcessingIndicatorConfiguration) -> some View {
self.content(configuration).typeErased
}
}

public struct ProcessingIndicatorConfiguration {
public let optionalTitle: OptionalTitle

public typealias OptionalTitle = ConfigurationViewWrapper
}

public struct ProcessingIndicatorFioriStyle: ProcessingIndicatorStyle {
public func makeBody(_ configuration: ProcessingIndicatorConfiguration) -> some View {
ProcessingIndicator(configuration)
.optionalTitleStyle(OptionalTitleFioriStyle(processingIndicatorConfiguration: configuration))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3657,6 +3657,41 @@ public extension PlaceholderTextFieldStyle where Self == PlaceholderTextFieldPla
}
}

// MARK: ProcessingIndicatorStyle

public extension ProcessingIndicatorStyle where Self == ProcessingIndicatorBaseStyle {
static var base: ProcessingIndicatorBaseStyle {
ProcessingIndicatorBaseStyle()
}
}

public extension ProcessingIndicatorStyle where Self == ProcessingIndicatorFioriStyle {
static var fiori: ProcessingIndicatorFioriStyle {
ProcessingIndicatorFioriStyle()
}
}

public struct ProcessingIndicatorOptionalTitleStyle: ProcessingIndicatorStyle {
let style: any OptionalTitleStyle

public func makeBody(_ configuration: ProcessingIndicatorConfiguration) -> some View {
ProcessingIndicator(configuration)
.optionalTitleStyle(self.style)
.typeErased
}
}

public extension ProcessingIndicatorStyle where Self == ProcessingIndicatorOptionalTitleStyle {
static func optionalTitleStyle(_ style: some OptionalTitleStyle) -> ProcessingIndicatorOptionalTitleStyle {
ProcessingIndicatorOptionalTitleStyle(style: style)
}

static func optionalTitleStyle(@ViewBuilder content: @escaping (OptionalTitleConfiguration) -> some View) -> ProcessingIndicatorOptionalTitleStyle {
let style = AnyOptionalTitleStyle(content)
return ProcessingIndicatorOptionalTitleStyle(style: style)
}
}

// MARK: ProfileHeaderStyle

public extension ProfileHeaderStyle where Self == ProfileHeaderBaseStyle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1452,6 +1452,27 @@ extension EnvironmentValues {
}
}

// MARK: ProcessingIndicatorStyle

struct ProcessingIndicatorStyleStackKey: EnvironmentKey {
static let defaultValue: [any ProcessingIndicatorStyle] = []
}

extension EnvironmentValues {
var processingIndicatorStyle: any ProcessingIndicatorStyle {
self.processingIndicatorStyleStack.last ?? .base.concat(.fiori)
}

var processingIndicatorStyleStack: [any ProcessingIndicatorStyle] {
get {
self[ProcessingIndicatorStyleStackKey.self]
}
set {
self[ProcessingIndicatorStyleStackKey.self] = newValue
}
}
}

// MARK: ProfileHeaderStyle

struct ProfileHeaderStyleStackKey: EnvironmentKey {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1940,6 +1940,34 @@ public extension PlaceholderTextFieldStyle {
}
}

// MARK: ProcessingIndicatorStyle

extension ModifiedStyle: ProcessingIndicatorStyle where Style: ProcessingIndicatorStyle {
public func makeBody(_ configuration: ProcessingIndicatorConfiguration) -> some View {
ProcessingIndicator(configuration)
.processingIndicatorStyle(self.style)
.modifier(self.modifier)
}
}

public struct ProcessingIndicatorStyleModifier<Style: ProcessingIndicatorStyle>: ViewModifier {
let style: Style

public func body(content: Content) -> some View {
content.processingIndicatorStyle(self.style)
}
}

public extension ProcessingIndicatorStyle {
func modifier(_ modifier: some ViewModifier) -> some ProcessingIndicatorStyle {
ModifiedStyle(style: self, modifier: modifier)
}

func concat(_ style: some ProcessingIndicatorStyle) -> some ProcessingIndicatorStyle {
style.modifier(ProcessingIndicatorStyleModifier(style: self))
}
}

// MARK: ProfileHeaderStyle

extension ModifiedStyle: ProfileHeaderStyle where Style: ProfileHeaderStyle {
Expand Down
Loading
Loading