Add UI to record a voice message from the composer toolbar (#1892)

This commit is contained in:
Nicolas Mauri
2023-10-16 17:18:51 +02:00
committed by GitHub
parent 0d72554e6f
commit 9ab3b20a49
43 changed files with 1241 additions and 87 deletions
@@ -67,7 +67,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
func processItemTap(_ itemID: TimelineItemIdentifier) async -> RoomTimelineControllerAction { .none }
func sendMessage(_ message: String, html: String?, inReplyTo itemID: TimelineItemIdentifier?) async { }
func toggleReaction(_ reaction: String, to itemID: TimelineItemIdentifier) async { }
func editMessage(_ newMessage: String, html: String?, original itemID: TimelineItemIdentifier) async { }
@@ -90,6 +90,8 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
func playPauseAudio(for itemID: TimelineItemIdentifier) async { }
func pauseAudio() { }
func seekAudio(for itemID: TimelineItemIdentifier, progress: Double) async { }
// MARK: - UI Test signalling
@@ -240,6 +240,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
if let playerState = timelineAudioPlayerStates[itemID] {
return playerState
}
let playerState = AudioPlayerState(duration: voiceMessageRoomTimelineItem.content.duration,
waveform: voiceMessageRoomTimelineItem.content.waveform)
timelineAudioPlayerStates[itemID] = playerState
@@ -278,6 +279,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
// Load content
do {
let url = try await voiceMessageMediaManager.loadVoiceMessageFromSource(source, body: nil)
// Make sure that the player is still attached, as it may have been detached while waiting for the voice message to be loaded.
if playerState.isAttached {
player.load(mediaSource: source, using: url)
@@ -297,10 +299,16 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
}
}
func pauseAudio() {
timelineAudioPlayerStates.forEach { _, playerState in
playerState.detachAudioPlayer()
}
}
func seekAudio(for itemID: TimelineItemIdentifier, progress: Double) async {
await timelineAudioPlayerStates[itemID]?.updateState(progress: progress)
}
// MARK: - Private
@objc private func contentSizeCategoryDidChange() {
@@ -52,7 +52,7 @@ protocol RoomTimelineControllerProtocol {
func sendReadReceipt(for itemID: TimelineItemIdentifier) async -> Result<Void, RoomTimelineControllerError>
func sendMessage(_ message: String, html: String?, inReplyTo itemID: TimelineItemIdentifier?) async
func editMessage(_ newMessage: String, html: String?, original itemID: TimelineItemIdentifier) async
func toggleReaction(_ reaction: String, to itemID: TimelineItemIdentifier) async
@@ -69,6 +69,8 @@ protocol RoomTimelineControllerProtocol {
func playPauseAudio(for itemID: TimelineItemIdentifier) async
func pauseAudio()
func seekAudio(for itemID: TimelineItemIdentifier, progress: Double) async
}
@@ -18,16 +18,16 @@ import SwiftUI
struct VoiceMessageRoomPlaybackView: View {
@ObservedObject var playerState: AudioPlayerState
@ScaledMetric private var waveformLineWidth = 2.0
@ScaledMetric private var waveformLinePadding = 2.0
let onPlayPause: () -> Void
let onSeek: (Double) -> Void
let onScrubbing: (Bool) -> Void
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
@State private var sendFeedback = false
@ScaledMetric private var waveformLineWidth = 2.0
@ScaledMetric private var waveformLinePadding = 2.0
private let waveformMaxWidth: CGFloat = 150
@ScaledMetric private var playPauseButtonSize = 32
@ScaledMetric private var playPauseImagePadding = 8
@@ -67,6 +67,7 @@ struct VoiceMessageRoomPlaybackView: View {
HStack {
playPauseButton
Text(timeLabelContent)
.lineLimit(1)
.font(.compound.bodySMSemibold)
.foregroundColor(.compound.textSecondary)
.monospacedDigit()
@@ -99,7 +100,6 @@ struct VoiceMessageRoomPlaybackView: View {
}
})
}
.frame(maxWidth: waveformMaxWidth)
}
.onChange(of: dragState) { newDragState in
switch newDragState {
@@ -139,6 +139,7 @@ struct VoiceMessageRoomPlaybackView: View {
.offset(x: playerState.playbackState == .playing ? 0 : 2)
.aspectRatio(contentMode: .fit)
.foregroundColor(.compound.iconSecondary)
.accessibilityLabel(playerState.playbackState == .playing ? L10n.a11yPause : L10n.a11yPlay)
}
}
}