From 640b1d874398f7b6b769f7b1153c19890e47d06b Mon Sep 17 00:00:00 2001 From: hengyi-zhang Date: Wed, 13 Nov 2024 11:02:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20[JIRA:HCPSDKFIORIUIKIT-2?= =?UTF-8?q?717]=20Feedback=20Patterns=20(#867)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 [JIRA:HCPSDKFIORIUIKIT-2717] Feedback Patterns 1. Replace example icons 2. Dismiss banner message when modal sheet appear * feat: 🎸 [JIRA:HCPSDKFIORIUIKIT-2717] Feedback Patterns --------- Co-authored-by: dyongxu <61523257+dyongxu@users.noreply.github.com> --- .../BannerMultiMessageCustomInitExample.swift | 12 ++++---- .../BannerMultiMessageExample.swift | 10 ++++--- .../BannerMessageStyle.fiori.swift | 25 +++++++++++++++-- .../BannerMultiMessageSheetStyle.fiori.swift | 28 +++++++++++++++---- 4 files changed, 58 insertions(+), 17 deletions(-) diff --git a/Apps/Examples/Examples/FioriSwiftUICore/BannerMessage/BannerMultiMessageCustomInitExample.swift b/Apps/Examples/Examples/FioriSwiftUICore/BannerMessage/BannerMultiMessageCustomInitExample.swift index b5f3b6fcf..25e56fb87 100644 --- a/Apps/Examples/Examples/FioriSwiftUICore/BannerMessage/BannerMultiMessageCustomInitExample.swift +++ b/Apps/Examples/Examples/FioriSwiftUICore/BannerMessage/BannerMultiMessageCustomInitExample.swift @@ -78,7 +78,7 @@ struct BannerMultiMessageCustomInitExample: View { }, turnOnSectionHeader: self.turnOnSectionHeader, messageItemView: { id in if let (message, category) = getItemData(with: id) { BannerMessage(icon: { - message.icon + (message.icon ?? EmptyView()).typeErased }, title: { Text(self.attributedMessageTitle(title: message.title, typeDesc: message.typeDesc)) }, closeAction: { @@ -328,7 +328,7 @@ struct BannerMultiMessageCustomInitExample: View { if self.firstName.isEmpty { let tips = "First name is required." self.firstNameErrorMessage = AttributedString(tips) - warningMessages.append(BannerMessageItemModel(id: self.firstNameId, icon: Image(fioriName: "fiori.warning"), title: tips, messageType: .critical)) + warningMessages.append(BannerMessageItemModel(id: self.firstNameId, icon: Image(fioriName: "fiori.warning2"), title: tips, messageType: .critical)) } else if self.firstName.count > 20 { let tips = "First name is too long." self.firstNameErrorMessage = AttributedString(tips) @@ -336,13 +336,15 @@ struct BannerMultiMessageCustomInitExample: View { } else { let tips = "First name correct." self.firstNameErrorMessage = AttributedString() - informationMessages.append(BannerMessageItemModel(id: self.firstNameId, icon: Image(fioriName: "fiori.hint"), title: tips, messageType: .positive)) + informationMessages.append(BannerMessageItemModel(id: self.firstNameId, icon: EmptyView(), title: tips, messageType: .positive)) + + informationMessages.append(BannerMessageItemModel(id: UUID(), icon: EmptyView(), title: tips, messageType: .positive)) } if self.lastName.isEmpty { let tips = "Last name is required." self.lastNameErrorMessage = AttributedString(tips) - warningMessages.append(BannerMessageItemModel(id: self.lastNameId, icon: Image(fioriName: "fiori.warning"), title: tips, messageType: .critical)) + warningMessages.append(BannerMessageItemModel(id: self.lastNameId, icon: Image(fioriName: "fiori.warning2"), title: tips, messageType: .critical)) } else if self.lastName.count > 20 { let tips = "Last name is too long." self.lastNameErrorMessage = AttributedString(tips) @@ -356,7 +358,7 @@ struct BannerMultiMessageCustomInitExample: View { if self.emailAddress.isEmpty { let tips = "Email address is required!" self.emailAddressErrorMessage = AttributedString(tips) - warningMessages.append(BannerMessageItemModel(id: self.emailAddressId, icon: Image(fioriName: "fiori.warning"), title: tips, messageType: .critical)) + warningMessages.append(BannerMessageItemModel(id: self.emailAddressId, icon: Image(fioriName: "fiori.warning2"), title: tips, messageType: .critical)) } else if self.isEmailInvalid { let tips = "Email address is Invalid! This can be multiple lines. This can be multiple lines. This can be multiple lines. This can be multiple lines. This can be multiple lines. This can be multiple lines. This can be multiple lines. This can be multiple lines." self.emailAddressErrorMessage = AttributedString(tips) diff --git a/Apps/Examples/Examples/FioriSwiftUICore/BannerMessage/BannerMultiMessageExample.swift b/Apps/Examples/Examples/FioriSwiftUICore/BannerMessage/BannerMultiMessageExample.swift index bba9ce66a..1d4abc94e 100644 --- a/Apps/Examples/Examples/FioriSwiftUICore/BannerMessage/BannerMultiMessageExample.swift +++ b/Apps/Examples/Examples/FioriSwiftUICore/BannerMessage/BannerMultiMessageExample.swift @@ -216,7 +216,7 @@ struct BannerMultiMessageExample: View { if self.firstName.isEmpty { let tips = "First name is required." self.firstNameErrorMessage = AttributedString(tips) - warningMessages.append(BannerMessageItemModel(id: self.firstNameId, icon: Image(fioriName: "fiori.warning"), title: tips, messageType: .critical)) + warningMessages.append(BannerMessageItemModel(id: self.firstNameId, icon: Image(fioriName: "fiori.warning2"), title: tips, messageType: .critical)) } else if self.firstName.count > 20 { let tips = "First name is too long." self.firstNameErrorMessage = AttributedString(tips) @@ -224,13 +224,15 @@ struct BannerMultiMessageExample: View { } else { let tips = "First name correct." self.firstNameErrorMessage = AttributedString() - informationMessages.append(BannerMessageItemModel(id: self.firstNameId, icon: Image(fioriName: "fiori.hint"), title: tips, messageType: .positive)) + informationMessages.append(BannerMessageItemModel(id: self.firstNameId, icon: Image(fioriName: "fiori.home"), title: tips + " Developer custom icon.", messageType: .positive)) + informationMessages.append(BannerMessageItemModel(id: UUID(), icon: EmptyView(), title: tips + " Empty icon.", messageType: .positive)) + informationMessages.append(BannerMessageItemModel(id: UUID(), icon: nil, title: tips + " SDK default icon.", messageType: .positive)) } if self.lastName.isEmpty { let tips = "Last name is required." self.lastNameErrorMessage = AttributedString(tips) - warningMessages.append(BannerMessageItemModel(id: self.lastNameId, icon: Image(fioriName: "fiori.warning"), title: tips, messageType: .critical)) + warningMessages.append(BannerMessageItemModel(id: self.lastNameId, icon: Image(fioriName: "fiori.warning2"), title: tips, messageType: .critical)) } else if self.lastName.count > 20 { let tips = "Last name is too long." self.lastNameErrorMessage = AttributedString(tips) @@ -244,7 +246,7 @@ struct BannerMultiMessageExample: View { if self.emailAddress.isEmpty { let tips = "Email address is required!" self.emailAddressErrorMessage = AttributedString(tips) - warningMessages.append(BannerMessageItemModel(id: self.emailAddressId, icon: Image(fioriName: "fiori.warning"), title: tips, messageType: .critical)) + warningMessages.append(BannerMessageItemModel(id: self.emailAddressId, icon: Image(fioriName: "fiori.warning2"), title: tips, messageType: .critical)) } else if self.isEmailInvalid { let tips = "Email address is Invalid!" self.emailAddressErrorMessage = AttributedString(tips) diff --git a/Sources/FioriSwiftUICore/_FioriStyles/BannerMessageStyle.fiori.swift b/Sources/FioriSwiftUICore/_FioriStyles/BannerMessageStyle.fiori.swift index 213b0152e..fa7b9b973 100644 --- a/Sources/FioriSwiftUICore/_FioriStyles/BannerMessageStyle.fiori.swift +++ b/Sources/FioriSwiftUICore/_FioriStyles/BannerMessageStyle.fiori.swift @@ -317,7 +317,7 @@ public extension View { } struct BannerMessageModifier: ViewModifier { - let icon: any View + let icon: (any View)? var title: (any View)? @Binding var isPresented: Bool @Binding var pushContentDown: Bool @@ -337,7 +337,7 @@ struct BannerMessageModifier: ViewModifier { @State private var showingMessageDetail: Bool = false - init(icon: any View, title: (any View)? = nil, isPresented: Binding, pushContentDown: Binding, bannerTapped: (() -> Void)? = nil, viewDetailAction: ((UUID) -> Void)? = nil, alignment: HorizontalAlignment, hideSeparator: Bool, messageType: BannerMultiMessageType, turnOnSectionHeader: Bool, showDetailLink: Bool, bannerMultiMessages: Binding<[BannerMessageListModel]>) { + init(icon: (any View)? = nil, title: (any View)? = nil, isPresented: Binding, pushContentDown: Binding, bannerTapped: (() -> Void)? = nil, viewDetailAction: ((UUID) -> Void)? = nil, alignment: HorizontalAlignment, hideSeparator: Bool, messageType: BannerMultiMessageType, turnOnSectionHeader: Bool, showDetailLink: Bool, bannerMultiMessages: Binding<[BannerMessageListModel]>) { self.icon = icon self.title = title _isPresented = isPresented @@ -408,9 +408,24 @@ struct BannerMessageModifier: ViewModifier { return NSLocalizedString(key + (count > 1 ? "s" : ""), tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: "") } + @ViewBuilder var defaultIcon: some View { + switch self.messageType { + case .neutral: + Image(fioriName: "fiori.hint") + case .informative: + Image(fioriName: "fiori.hint") + case .positive: + Image(fioriName: "fiori.hint") + case .critical: + Image(fioriName: "fiori.warning2") + case .negative: + Image(fioriName: "fiori.notification.3") + } + } + @ViewBuilder var bannerMessage: some View { BannerMessage(icon: { - self.icon + (self.icon ?? self.defaultIcon).typeErased }, title: { if let title = self.title { AnyView(title) @@ -419,6 +434,10 @@ struct BannerMessageModifier: ViewModifier { .environment(\.openURL, OpenURLAction(handler: { url in if url.absoluteString == "ViewDetails" { self.showingMessageDetail = true + + if UIDevice.current.userInterfaceIdiom == .phone { + self.isPresented = false + } } return .handled })) diff --git a/Sources/FioriSwiftUICore/_FioriStyles/BannerMultiMessageSheetStyle.fiori.swift b/Sources/FioriSwiftUICore/_FioriStyles/BannerMultiMessageSheetStyle.fiori.swift index fd238011f..8224eced8 100644 --- a/Sources/FioriSwiftUICore/_FioriStyles/BannerMultiMessageSheetStyle.fiori.swift +++ b/Sources/FioriSwiftUICore/_FioriStyles/BannerMultiMessageSheetStyle.fiori.swift @@ -16,7 +16,7 @@ import SwiftUI public struct BannerMessageItemModel: Identifiable { public var id: UUID /// Banner icon - public var icon: any View + public var icon: (any View)? /// Banner title public var title: String /// Message Type @@ -37,7 +37,7 @@ public struct BannerMessageItemModel: Identifiable { } } - public init(id: UUID = UUID(), icon: any View, title: String, messageType: BannerMultiMessageType) { + public init(id: UUID = UUID(), icon: (any View)?, title: String, messageType: BannerMultiMessageType) { self.id = id self.icon = icon self.title = title @@ -200,6 +200,21 @@ public struct BannerMultiMessageSheetBaseStyle: BannerMultiMessageSheetStyle { } } + func defaultIcon(_ messageType: BannerMultiMessageType) -> some View { + switch messageType { + case .neutral: + Image(fioriName: "fiori.hint") + case .informative: + Image(fioriName: "fiori.hint") + case .positive: + Image(fioriName: "fiori.hint") + case .critical: + Image(fioriName: "fiori.warning2") + case .negative: + Image(fioriName: "fiori.notification.3") + } + } + // swiftlint:disable:next function_body_length public func makeBody(_ configuration: BannerMultiMessageSheetConfiguration) -> some View { VStack(spacing: 0, content: { @@ -249,9 +264,12 @@ public struct BannerMultiMessageSheetBaseStyle: BannerMultiMessageSheetStyle { .foregroundStyle(Color.preferredColor(.secondaryLabel)) Spacer() - _Action(actionText: _ClearActionDefault().actionText, didSelectAction: { + Button { self.removeCategoryAction(configuration, category: element.category) - }) + } label: { + Text(_ClearActionDefault().actionText ?? "") + } + .buttonStyle(PlainButtonStyle()) .font(.fiori(forTextStyle: .subheadline)) .foregroundStyle(Color.preferredColor(.tintColor)) } @@ -265,7 +283,7 @@ public struct BannerMultiMessageSheetBaseStyle: BannerMultiMessageSheetStyle { AnyView(configuration.messageItemView(message.id)) } else { BannerMessage(icon: { - message.icon + (message.icon ?? self.defaultIcon(message.messageType)).typeErased }, title: { Text(self.attributedMessageTitle(title: message.title, typeDesc: message.typeDesc)) }, closeAction: {