From c020ba2d855c0de7744aff75b2d3f40ea2822d4c Mon Sep 17 00:00:00 2001 From: Nicolas Mauri Date: Wed, 25 Oct 2023 17:39:57 +0200 Subject: [PATCH] Fix: do not hide keyboard when recording a voice message (#1958) --- .../ComposerToolbarModels.swift | 9 +++ .../ComposerToolbarViewModel.swift | 1 - .../View/ComposerToolbar.swift | 63 ++++++++++++------- .../test_composerToolbar.Voice-Message.png | 4 +- 4 files changed, 52 insertions(+), 25 deletions(-) diff --git a/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarModels.swift b/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarModels.swift index ea601aba6..75e7f7116 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarModels.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarModels.swift @@ -106,6 +106,15 @@ struct ComposerToolbarViewState: BindableState { } return composerEmpty } + + var isVoiceMessageModeActivated: Bool { + switch composerMode { + case .recordVoiceMessage, .previewVoiceMessage: + return true + default: + return false + } + } } struct ComposerToolbarViewStateBindings { diff --git a/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift b/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift index b47ca3f27..ef8a04d3d 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift @@ -230,7 +230,6 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool case .default: break case .recordVoiceMessage(let audioRecorderState): - state.bindings.composerFocused = false state.audioRecorderState = audioRecorderState case .previewVoiceMessage(let audioPlayerState, _, _): state.audioPlayerState = audioPlayerState diff --git a/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift b/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift index 0338e0783..ceba67e87 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift @@ -73,7 +73,7 @@ struct ComposerToolbar: View { } private var topBar: some View { - HStack(alignment: .bottom, spacing: 5) { + topBarLayout { mainTopBarContent if !context.composerActionsEnabled { @@ -105,31 +105,32 @@ struct ComposerToolbar: View { .padding(.leading, 7) } } + + private var topBarLayout: some Layout { + HStackLayout(alignment: .bottom, spacing: 5) + } @ViewBuilder private var mainTopBarContent: some View { - switch context.viewState.composerMode { - case .recordVoiceMessage(let state) where context.viewState.enableVoiceMessageComposer: - VoiceMessageRecordingComposer(recorderState: state) - .padding(.leading, 12) - case .previewVoiceMessage(let state, let waveform, let isUploading) where context.viewState.enableVoiceMessageComposer: - Group { - voiceMessageTrashButton - voiceMessagePreviewComposer(audioPlayerState: state, waveform: waveform) - } - .disabled(isUploading) - default: - if !context.composerActionsEnabled { - RoomAttachmentPicker(context: context) - } - messageComposer - .environmentObject(context) - .onTapGesture { - guard !composerFocused else { return } - composerFocused = true + ZStack { + topBarLayout { + if !context.composerActionsEnabled { + RoomAttachmentPicker(context: context) } - .padding(.leading, context.composerActionsEnabled ? 7 : 0) - .padding(.trailing, context.composerActionsEnabled ? 4 : 0) + messageComposer + .environmentObject(context) + .onTapGesture { + guard !composerFocused else { return } + composerFocused = true + } + .padding(.leading, context.composerActionsEnabled ? 7 : 0) + .padding(.trailing, context.composerActionsEnabled ? 4 : 0) + } + .opacity(context.viewState.isVoiceMessageModeActivated ? 0 : 1) + + if context.viewState.isVoiceMessageModeActivated { + voiceMessageContent + } } } @@ -237,6 +238,24 @@ struct ComposerToolbar: View { // MARK: - Voice message + @ViewBuilder + private var voiceMessageContent: some View { + // Display the voice message composer above to keep the focus and keep the keyboard open if it's already open. + switch context.viewState.composerMode { + case .recordVoiceMessage(let state) where context.viewState.enableVoiceMessageComposer: + VoiceMessageRecordingComposer(recorderState: state) + .padding(.leading, 12) + case .previewVoiceMessage(let state, let waveform, let isUploading) where context.viewState.enableVoiceMessageComposer: + topBarLayout { + voiceMessageTrashButton + voiceMessagePreviewComposer(audioPlayerState: state, waveform: waveform) + } + .disabled(isUploading) + default: + EmptyView() + } + } + private var voiceMessageRecordingButton: some View { VoiceMessageRecordingButton { showVoiceMessageRecordingTooltip = false diff --git a/UnitTests/__Snapshots__/PreviewTests/test_composerToolbar.Voice-Message.png b/UnitTests/__Snapshots__/PreviewTests/test_composerToolbar.Voice-Message.png index a871362dc..f3da7368d 100644 --- a/UnitTests/__Snapshots__/PreviewTests/test_composerToolbar.Voice-Message.png +++ b/UnitTests/__Snapshots__/PreviewTests/test_composerToolbar.Voice-Message.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d45505a9c6125393c99b7cd29846a1f712eb32ce8f8c044d7483fefb48b7db5 -size 95515 +oid sha256:b75d67814719e5a44c8e647a8e4fb2b1f9b893ccfbc2fcc9939270e40bc2fc0f +size 95523