// // Copyright 2025 Element Creations Ltd. // Copyright 2023-2025 New Vector Ltd. // // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. // Please see LICENSE files in the repository root for full details. // import SwiftUI nonisolated struct EstimatedWaveform: Equatable, Hashable { static let dataRange: ClosedRange = 0...1024 let data: [UInt16] } extension EstimatedWaveform { /// Maps the `data` array to Float values in the range 0...1 respecting the `Self.dataRange` limits. /// Up to `maxSamplesCount` will be returned in the output array func normalisedData(maxSamplesCount: Int) -> [Float] { guard maxSamplesCount > 0 else { return [] } // Filter the data to keep only the expected number of samples let result: [UInt16] if data.count > maxSamplesCount { result = (0.. CGSize) { value = nextValue() } } private struct WaveformShape: Shape { let lineWidth: CGFloat let linePadding: CGFloat let waveformData: [Float] var minimumGraphAmplitude: CGFloat = 1.0 func path(in rect: CGRect) -> Path { let width = rect.size.width let height = rect.size.height let centerY = rect.size.height / 2 var xOffset: CGFloat = lineWidth / 2 var index = 0 var path = Path() while xOffset <= width { let sample = CGFloat(index >= waveformData.count ? 0 : waveformData[index]) let drawingAmplitude = max(minimumGraphAmplitude, sample * (height - 2)) path.move(to: CGPoint(x: xOffset, y: centerY - drawingAmplitude / 2)) path.addLine(to: CGPoint(x: xOffset, y: centerY + drawingAmplitude / 2)) xOffset += lineWidth + linePadding index += 1 } return path } } struct EstimatedWaveformView_Previews: PreviewProvider, TestablePreview { static var previews: some View { // Wrap the WaveformView in a VStack otherwise the preview test will fail (because of Prefire / GeometryReader) VStack(spacing: 0) { EstimatedWaveformView(waveform: EstimatedWaveform.mockWaveform, progress: 0.5) .frame(width: 140, height: 50) } } }