Skip to content

Commit e1d6e89

Browse files
Fixed reactions overlay interface orientation updates
1 parent d441e7b commit e1d6e89

File tree

2 files changed

+65
-9
lines changed

2 files changed

+65
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1111

1212
### 🐞 Fixed
1313
- Online indicator updates in the header view
14+
- Reactions overlay interface orientation updates
1415

1516
# [4.35.1](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.35.1)
1617
_August 10, 2023_

Sources/StreamChatSwiftUI/ChatChannel/Reactions/ReactionsOverlayView.swift

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
1414
@State private var popIn = false
1515
@State private var willPopOut = false
1616
@State private var screenHeight = UIScreen.main.bounds.size.height
17+
@State private var screenWidth: CGFloat?
18+
@State private var initialWidth: CGFloat?
19+
@State private var orientationChanged = false
20+
@State private var initialOrigin: CGFloat?
1721

1822
var factory: Factory
1923
var channel: ChatChannel
@@ -61,11 +65,17 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
6165

6266
public var body: some View {
6367
ZStack(alignment: .topLeading) {
64-
factory.makeReactionsBackgroundView(
65-
currentSnapshot: currentSnapshot,
66-
popInAnimationInProgress: !popIn
67-
)
68-
.offset(y: spacing > 0 ? screenHeight - currentSnapshot.size.height : 0)
68+
ZStack {
69+
if !orientationChanged {
70+
factory.makeReactionsBackgroundView(
71+
currentSnapshot: currentSnapshot,
72+
popInAnimationInProgress: !popIn
73+
)
74+
.offset(y: spacing > 0 ? screenHeight - currentSnapshot.size.height : 0)
75+
} else {
76+
Color.gray.opacity(0.4)
77+
}
78+
}
6979
.transition(.opacity)
7080
.onTapGesture {
7181
dismissReactionsOverlay() { /* No additional handling. */ }
@@ -90,7 +100,10 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
90100
GeometryReader { reader in
91101
let frame = reader.frame(in: .local)
92102
let height = frame.height
103+
let width = frame.width
93104
Color.clear.preference(key: HeightPreferenceKey.self, value: height)
105+
Color.clear.preference(key: WidthPreferenceKey.self, value: width)
106+
94107
VStack(alignment: .leading) {
95108
Group {
96109
if messageDisplayInfo.frame.height > messageContainerHeight {
@@ -116,7 +129,7 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
116129
.scaleEffect(popIn || willPopOut ? 1 : 0.95)
117130
.animation(willPopOut ? .easeInOut : popInAnimation, value: popIn)
118131
.offset(
119-
x: messageDisplayInfo.frame.origin.x - diffWidth(proxy: reader)
132+
x: messageOriginX(proxy: reader)
120133
)
121134
.overlay(
122135
channel.config.reactionsEnabled ?
@@ -133,7 +146,7 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
133146
.opacity(willPopOut ? 0 : 1)
134147
.animation(willPopOut ? .easeInOut : popInAnimation, value: popIn)
135148
.offset(
136-
x: messageDisplayInfo.frame.origin.x - diffWidth(proxy: reader),
149+
x: messageOriginX(proxy: reader),
137150
y: popIn ? -24 : -messageContainerHeight / 2
138151
)
139152
.accessibilityElement(children: .contain)
@@ -182,20 +195,34 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
182195
}
183196
}
184197
.offset(y: !popIn ? (messageDisplayInfo.frame.origin.y - spacing) : originY)
198+
.onAppear {
199+
self.initialOrigin = messageDisplayInfo.frame.origin.x - diffWidth(proxy: reader)
200+
}
185201
}
186202
}
187203
.onPreferenceChange(HeightPreferenceKey.self) { value in
188204
if let value = value, value != screenHeight {
189205
self.screenHeight = value
190206
}
191207
}
208+
.onPreferenceChange(WidthPreferenceKey.self) { value in
209+
if initialWidth == nil {
210+
initialWidth = value
211+
}
212+
self.screenWidth = value
213+
}
192214
.edgesIgnoringSafeArea(.all)
193-
.background(Color(colors.background))
215+
.background(orientationChanged ? nil : Color(colors.background))
194216
.onAppear {
195217
popIn = true
196218
}
197219
.accessibilityElement(children: .contain)
198220
.accessibilityIdentifier("ReactionsOverlayView")
221+
.onRotate { orientation in
222+
if isIPad {
223+
self.orientationChanged = true
224+
}
225+
}
199226
}
200227

201228
private func dismissReactionsOverlay(completion: @escaping () -> Void) {
@@ -215,11 +242,21 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
215242
if popIn {
216243
return originX
217244
} else if willPopOut {
218-
return messageDisplayInfo.frame.origin.x - diffWidth(proxy: reader)
245+
return messageOriginX(proxy: reader)
219246
} else {
220247
return sentByCurrentUser ? messageActionsWidth : 0
221248
}
222249
}
250+
251+
private func messageOriginX(proxy: GeometryProxy) -> CGFloat {
252+
let origin = messageDisplayInfo.frame.origin.x - diffWidth(proxy: proxy)
253+
if let initialWidth, let initialOrigin, let screenWidth, abs(initialWidth - screenWidth) > 5 {
254+
let diff = initialWidth - initialOrigin
255+
let newOrigin = screenWidth - diff
256+
return newOrigin
257+
}
258+
return initialOrigin ?? origin
259+
}
223260

224261
private var messageContainerHeight: CGFloat {
225262
let maxAllowed = screenHeight / 2
@@ -310,3 +347,21 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
310347
return width
311348
}
312349
}
350+
351+
struct DeviceRotationViewModifier: ViewModifier {
352+
let action: (UIDeviceOrientation) -> Void
353+
354+
func body(content: Content) -> some View {
355+
content
356+
.onAppear()
357+
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
358+
action(UIDevice.current.orientation)
359+
}
360+
}
361+
}
362+
363+
extension View {
364+
func onRotate(perform action: @escaping (UIDeviceOrientation) -> Void) -> some View {
365+
self.modifier(DeviceRotationViewModifier(action: action))
366+
}
367+
}

0 commit comments

Comments
 (0)