diff --git a/ElementX/Sources/Other/SwiftUI/Layout/ViewFrameReader.swift b/ElementX/Sources/Other/SwiftUI/Layout/ViewFrameReader.swift index fdb198c7b..83ca80bd3 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/ViewFrameReader.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/ViewFrameReader.swift @@ -28,7 +28,7 @@ import SwiftUI /// ``` struct ViewFrameReader: View { @Binding var frame: CGRect - let coordinateSpace: CoordinateSpace = .local + var coordinateSpace: CoordinateSpace = .local var body: some View { GeometryReader { geometry in diff --git a/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift b/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift index ceba67e87..080c732a8 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift @@ -32,12 +32,13 @@ struct ComposerToolbar: View { @State private var voiceMessageRecordingStartTime: Date? @State private var showVoiceMessageRecordingTooltip = false @ScaledMetric private var voiceMessageTooltipPointerHeight = 6 + @State private var voiceMessageRecordingButtonFrame: CGRect = .zero private let voiceMessageMinimumRecordingDuration = 1.0 private let voiceMessageTooltipDuration = 1.0 @State private var frame: CGRect = .zero - + var body: some View { VStack(spacing: 8) { topBar @@ -86,6 +87,9 @@ struct ComposerToolbar: View { .padding(.leading, 3) } else if context.viewState.enableVoiceMessageComposer { voiceMessageRecordingButton + .background { + ViewFrameReader(frame: $voiceMessageRecordingButtonFrame, coordinateSpace: .global) + } .padding(.leading, 4) } } @@ -290,7 +294,10 @@ struct ComposerToolbar: View { } private var voiceMessageRecordingButtonTooltipView: some View { - VoiceMessageRecordingButtonTooltipView(text: L10n.screenRoomVoiceMessageTooltip, pointerHeight: voiceMessageTooltipPointerHeight) + VoiceMessageRecordingButtonTooltipView(text: L10n.screenRoomVoiceMessageTooltip, + pointerHeight: voiceMessageTooltipPointerHeight, + pointerLocation: voiceMessageRecordingButtonFrame.midX, + pointerLocationCoordinateSpace: .global) .allowsHitTesting(false) .onAppear { DispatchQueue.main.asyncAfter(deadline: .now() + voiceMessageTooltipDuration) { @@ -299,6 +306,7 @@ struct ComposerToolbar: View { } } } + .padding(.horizontal, 8) } private func voiceMessagePreviewComposer(audioPlayerState: AudioPlayerState, waveform: WaveformSource) -> some View { diff --git a/ElementX/Sources/Screens/ComposerToolbar/View/VoiceMessageRecordingButtonTooltipView.swift b/ElementX/Sources/Screens/ComposerToolbar/View/VoiceMessageRecordingButtonTooltipView.swift index 2d996652c..f93ebaac1 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/View/VoiceMessageRecordingButtonTooltipView.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/View/VoiceMessageRecordingButtonTooltipView.swift @@ -24,7 +24,8 @@ struct VoiceMessageRecordingButtonTooltipView: View { var corners: UIRectCorner = .allCorners @ScaledMetric var pointerHeight: CGFloat = 6 @ScaledMetric var pointerWidth: CGFloat = 10 - @ScaledMetric var pointerOffset: CGFloat = 8 + var pointerLocation: CGFloat = 10 + var pointerLocationCoordinateSpace: CoordinateSpace = .local var body: some View { Text(text) @@ -32,27 +33,35 @@ struct VoiceMessageRecordingButtonTooltipView: View { .foregroundColor(.compound.textOnSolidPrimary) .padding(6) .background( - TooltipShape(radius: radius, - corners: corners, - pointerHeight: pointerHeight, - pointerWidth: pointerWidth, - pointerOffset: pointerOffset) - .fill(.compound.bgActionPrimaryRest) + GeometryReader { geometry in + TooltipShape(radius: radius, + corners: corners, + pointerHeight: pointerHeight, + pointerWidth: pointerWidth, + pointerLocation: localPointerLocation(using: geometry)) + .fill(.compound.bgActionPrimaryRest) + } ) - .padding(.trailing, 8) + } + + private func localPointerLocation(using geometry: GeometryProxy) -> CGFloat { + let frame = geometry.frame(in: pointerLocationCoordinateSpace) + let minX = radius + pointerWidth / 2 + let maxX = geometry.size.width - radius - pointerWidth / 2 + return min(max(minX, pointerLocation - frame.minX), maxX) } } private struct TooltipShape: Shape { - var radius: CGFloat = 4 - var corners: UIRectCorner = .allCorners - var pointerHeight: CGFloat = 6 - var pointerWidth: CGFloat = 10 - var pointerOffset: CGFloat = 8 + var radius: CGFloat + var corners: UIRectCorner + var pointerHeight: CGFloat + var pointerWidth: CGFloat + var pointerLocation: CGFloat func path(in rect: CGRect) -> Path { var path = Path() - + let width = rect.size.width let height = rect.size.height @@ -76,9 +85,9 @@ private struct TooltipShape: Shape { path.addArc(center: CGPoint(x: width - bottomRight, y: height - bottomRight), radius: bottomRight, startAngle: Angle(degrees: 0), endAngle: Angle(degrees: 90), clockwise: false) - path.addLine(to: CGPoint(x: width - pointerOffset, y: height)) - path.addLine(to: CGPoint(x: width - pointerOffset - (pointerWidth / 2.0), y: height + pointerHeight)) - path.addLine(to: CGPoint(x: width - pointerOffset - pointerWidth, y: height)) + path.addLine(to: CGPoint(x: pointerLocation + (pointerWidth / 2.0), y: height)) + path.addLine(to: CGPoint(x: pointerLocation, y: height + pointerHeight)) + path.addLine(to: CGPoint(x: pointerLocation - (pointerWidth / 2.0), y: height)) path.addLine(to: CGPoint(x: bottomLeft, y: height)) path.addArc(center: CGPoint(x: bottomLeft, y: height - bottomLeft), radius: bottomLeft, diff --git a/UnitTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButtonTooltipView.1.png b/UnitTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButtonTooltipView.1.png index 0351cc491..96bd54c22 100644 --- a/UnitTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButtonTooltipView.1.png +++ b/UnitTests/__Snapshots__/PreviewTests/test_voiceMessageRecordingButtonTooltipView.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b82dbb24ecf09d3fa08a0308181b83106f7e62935ee5f1201ef8ae1533e33ded -size 60029 +oid sha256:ffcce0a3fe8e27798377372f73090b72a27c986d36f4936701317d60571f5b92 +size 60040