@@ -13,95 +13,103 @@ struct NotificationPresenterView: View {
13
13
case vertical
14
14
case horizontal
15
15
}
16
-
17
- @State private var verticalDragTranslation : CGFloat = . zero
18
- @State private var horizontalDragTranslation : CGFloat = . zero
19
- @State private var minTranslationYForDismiss : CGFloat = . infinity
20
- @State private var minTranslationXForDismiss : CGFloat = . infinity
21
16
@State private var isTextLimited : Bool = true
22
17
@State private var dismissEdge : Edge = . top
23
- @State private var dragDirection : DragDirection ?
18
+ @State private var dragDirection : DragDirection ?
19
+ @State private var dynamicHeight : CGFloat = 0
20
+ @State private var notificationHeight : CGFloat = 0
21
+ @State private var offset : CGSize = . zero
24
22
25
23
let model : NotificationModel
26
24
let safeAreaInsets : EdgeInsets
27
25
let dismissAction : ( ) -> Void
28
26
29
27
var body : some View {
30
- NotificationView (
31
- isTextLimited: $isTextLimited,
32
- model: model
33
- )
34
- . padding ( [ . leading, . trailing] , 10 )
35
- . padding ( [ . top, . bottom] , 10 )
28
+ VStack {
29
+ NotificationView (
30
+ isTextLimited: $isTextLimited,
31
+ model: model
32
+ )
33
+ . padding ( 10 )
34
+ . padding ( [ . top, . bottom] , 10 )
35
+ . background (
36
+ GeometryReader { geometry in
37
+ Color . clear
38
+ . onAppear {
39
+ notificationHeight = geometry. size. height
40
+ print ( " onappier " )
41
+ }
42
+ . onChange ( of: geometry. size. height) { newValue in
43
+ notificationHeight = newValue
44
+ }
45
+ }
46
+ )
47
+ }
48
+ . frame ( minHeight: notificationHeight + dynamicHeight)
36
49
. overlay (
37
50
RoundedRectangle ( cornerRadius: 10 )
38
51
. stroke ( Color . init ( uiColor: . adamant. chatInputBarBorderColor) , lineWidth: 1 )
39
52
)
40
53
. background ( GeometryReader ( content: processGeometry) )
41
- . expanded ( axes: . horizontal)
42
- . offset ( y: verticalDragTranslation < . zero ? verticalDragTranslation : . zero)
43
- . offset ( x: horizontalDragTranslation < . zero ? horizontalDragTranslation : . zero)
44
- . gesture ( dragGesture)
45
54
. onTapGesture ( perform: onTap)
55
+ . gesture ( dragGesture)
46
56
. cornerRadius ( 10 )
47
57
. padding ( . horizontal, 15 )
48
58
. padding ( . top, safeAreaInsets. top)
59
+ . offset ( offset)
60
+ . animation ( . interactiveSpring( ) , value: offset)
49
61
. transition ( . move( edge: dismissEdge) )
50
62
}
51
63
}
52
-
64
+ private extension NotificationPresenterView {
65
+ func processGeometry( _ geometry: GeometryProxy ) -> some View {
66
+ return Color . init ( uiColor: . adamant. swipeBlockColor)
67
+ . cornerRadius ( 10 )
68
+ }
69
+ func onTap( ) {
70
+ model. tapHandler? . value ( )
71
+ dismissAction ( )
72
+ dismissEdge = . top
73
+ }
74
+ }
53
75
private extension NotificationPresenterView {
54
76
var dragGesture : some Gesture {
55
77
DragGesture ( )
56
- . onChanged {
57
- if dragDirection == nil {
58
- dragDirection = abs ( $0 . translation . height ) > abs ( $0 . translation . width ) ? . vertical : . horizontal
78
+ . onChanged { value in
79
+ if dragDirection == nil || ( abs ( value . translation . width ) <= 5 && abs ( value . translation . height ) <= 5 ) {
80
+ detectDragDirection ( value : value )
59
81
}
60
- switch dragDirection {
61
- case . vertical :
62
- verticalDragTranslation = $0 . translation . height
63
- case . horizontal :
64
- horizontalDragTranslation = $0 . translation. width
65
- case . none :
66
- break
82
+ if dragDirection == . vertical && isTextLimited {
83
+ dynamicHeight = max ( 0 , min ( value . translation . height , 30 ) )
84
+ }
85
+ if dragDirection == . vertical , value . translation . height < 0 {
86
+ offset = CGSize ( width : 0 , height : value . translation. height )
87
+ } else if dragDirection == . horizontal , value . translation . width < 0 {
88
+ offset = CGSize ( width : value . translation . width , height : 0 )
67
89
}
68
90
}
69
- . onEnded {
70
- if $0. velocity. height < - 100 || - $0. translation. height > minTranslationYForDismiss {
71
- dismissEdge = . top
72
- Task { dismissAction ( ) }
73
- } else if $0. velocity. width < - 100 || $0. translation. width > minTranslationXForDismiss {
74
- dismissEdge = . leading
75
- Task { dismissAction ( ) }
76
- } else if $0. velocity. height > - 100 || - $0. translation. height < minTranslationYForDismiss {
77
- withAnimation {
78
- horizontalDragTranslation = . zero
91
+ . onEnded { value in
92
+ if dragDirection == . vertical {
93
+ if value. translation. height > 25 {
94
+ model. cancelAutoDismiss? . value ( )
79
95
isTextLimited = false
96
+ } else if value. translation. height < - 30 {
97
+ Task { dismissAction ( ) }
80
98
}
81
- model. cancelAutoDismiss? . value ( )
82
- } else {
83
- withAnimation {
84
- verticalDragTranslation = . zero
85
- horizontalDragTranslation = . zero
99
+ } else if dragDirection == . horizontal {
100
+ if value. translation. width < - 100 {
101
+ dismissEdge = . leading
102
+ Task { dismissAction ( ) }
86
103
}
87
104
}
88
105
dragDirection = nil
106
+ dynamicHeight = 0
107
+ offset = . zero
89
108
}
90
109
}
91
110
92
- func processGeometry( _ geometry: GeometryProxy ) -> some View {
93
- DispatchQueue . main. async {
94
- minTranslationYForDismiss = geometry. size. height / 2
95
- minTranslationXForDismiss = geometry. size. width / 2
96
- }
97
-
98
- return Color . init ( uiColor: . adamant. swipeBlockColor)
99
- . cornerRadius ( 10 )
100
- }
101
-
102
- func onTap( ) {
103
- model. tapHandler? . value ( )
104
- dismissAction ( )
105
- dismissEdge = . top
111
+ func detectDragDirection( value: DragGesture . Value ) {
112
+ let horizontalDistance = abs ( value. translation. width) , verticalDistance = abs ( value. translation. height)
113
+ dragDirection = verticalDistance > horizontalDistance ? . vertical : . horizontal
106
114
}
107
115
}
0 commit comments