66#if canImport(FluentUI_common)
77import FluentUI_common
88#endif
9+ import Combine
910import SwiftUI
1011
1112/// Properties that can be used to customize the appearance of the `Notification`.
@@ -67,10 +68,17 @@ import SwiftUI
6768 ///
6869 /// If this property is nil, then this notification will use the background color defined by its design tokens.
6970 var backgroundGradient : LinearGradientInfo ? { get set }
71+ }
7072
71- /// Performs an animation emphasizing the notification.
72- /// The animation alternates between upward and downward movements with spring physics.
73- func bump( )
73+ /// Exposes public published properties that are observed by the `FluentNotification`. Enables
74+ /// easy interaction with the Notification for clients.
75+ @objc ( MSFFluentNotificationTriggerModel)
76+ public class FluentNotificationTriggerModel : NSObject , ObservableObject {
77+ /// Triggers the bump animation for the notification.
78+ ///
79+ /// Set this to `true` to trigger the bump animation. The value will be
80+ /// automatically reset to `false` after the animation is triggered.
81+ @Published public var shouldBump : Bool = false
7482}
7583
7684/// View that represents the Notification.
@@ -116,7 +124,9 @@ public struct FluentNotification: View, TokenizedControlView {
116124 defaultDismissButtonAction: ( ( ) -> Void ) ? = nil ,
117125 messageButtonAction: ( ( ) -> Void ) ? = nil ,
118126 showFromBottom: Bool = true ,
119- verticalOffset: CGFloat = 0.0 ) {
127+ verticalOffset: CGFloat = 0.0 ,
128+ triggerModel: FluentNotificationTriggerModel = FluentNotificationTriggerModel ( ) ,
129+ onDismiss: ( ( ) -> Void ) ? = nil ) {
120130 let state = MSFNotificationStateImpl ( style: style,
121131 message: message,
122132 attributedMessage: attributedMessage,
@@ -133,9 +143,11 @@ public struct FluentNotification: View, TokenizedControlView {
133143 messageButtonAction: messageButtonAction,
134144 showFromBottom: showFromBottom,
135145 verticalOffset: verticalOffset)
146+ state. onDismiss = onDismiss
136147 self . state = state
137148 self . shouldSelfPresent = shouldSelfPresent
138149 self . isFlexibleWidthToast = isFlexibleWidthToast && style. isToast
150+ self . triggerModel = triggerModel
139151
140152 self . tokenSet = NotificationTokenSet ( style: { state. style } )
141153
@@ -328,9 +340,9 @@ public struct FluentNotification: View, TokenizedControlView {
328340 . glassBackgroundEffect( in: RoundedRectangle ( cornerRadius: tokenSet [ . cornerRadius] . float) )
329341#endif // os(visionOS)
330342 . offset( y: - bumpVerticalOffset)
331- . onChange ( of: state . shouldPerformBump ) { _, shouldBump in
343+ . onChange ( of: triggerModel . shouldBump ) { _, shouldBump in
332344 if shouldBump {
333- state . shouldPerformBump = false
345+ triggerModel . shouldBump = false
334346 performBumpAnimated ( )
335347 }
336348 }
@@ -390,6 +402,7 @@ public struct FluentNotification: View, TokenizedControlView {
390402
391403 @Environment ( \. fluentTheme) var fluentTheme : FluentTheme
392404 @ObservedObject var state : MSFNotificationStateImpl
405+ @ObservedObject var triggerModel : FluentNotificationTriggerModel
393406
394407 /// The `dismissButtonAction` will be non-nil for the following cases:
395408 /// - The `state.actionButtonAction` is set but there is no custom title or trailing image. The `actionButtonAction`
@@ -522,9 +535,6 @@ class MSFNotificationStateImpl: ControlState, MSFNotificationState {
522535 /// Style to draw the control.
523536 @Published var style : MSFNotificationStyle
524537
525- /// Controls whether the bump animation should start
526- @Published internal var shouldPerformBump : Bool = false
527-
528538 @objc convenience init ( style: MSFNotificationStyle ) {
529539 self . init ( style: style,
530540 message: nil ,
@@ -578,10 +588,4 @@ class MSFNotificationStateImpl: ControlState, MSFNotificationState {
578588
579589 super. init ( )
580590 }
581-
582- @objc func bump( ) {
583- if !shouldPerformBump {
584- shouldPerformBump = true
585- }
586- }
587591}
0 commit comments