diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index a692ea1bf..c0b1dbf48 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -124,7 +124,6 @@ 12EC6BC99F373FE5C6EB9B64 /* TimelineMediaPreviewDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467498BEA681758BE2F80826 /* TimelineMediaPreviewDetailsView.swift */; }; 1307268DC41730E5BCF7D9A0 /* PollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 638790D3F915F0909315C47A /* PollView.swift */; }; 1318721F4E5F307586D98112 /* VoiceMessageButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8516302ACCA94A0E680AB3B /* VoiceMessageButton.swift */; }; - ES17LAX66UIQ5OAE6L2BQQE4 /* PlaybackSpeedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = HW13ISECOFUYATOTX2RU7GDG /* PlaybackSpeedButton.swift */; }; 13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */; }; 13CBC470FB619A6393A21908 /* RoomNotificationSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8296D6FB451E25CEC0767BBA /* RoomNotificationSettingsScreenCoordinator.swift */; }; 1443CEEE42491CF7CD8A146A /* XCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85A1941B874A3BE9CDDF43EF /* XCTestCase.swift */; }; @@ -496,6 +495,7 @@ 5618ED25F092DF5712003829 /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */; }; 562EFB9AB62B38830D9AA778 /* TimelineMediaFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */; }; 565868808A1DA565707394ED /* CurrentValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */; }; + 56C18ACF91DD20463B242460 /* AudioPlaybackSpeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78B4E56DBFFD4A7A39D10F5 /* AudioPlaybackSpeed.swift */; }; 56DACDD379A86A1F5DEFE7BE /* AuthenticationServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E75948AA1FE1D1A7809931F /* AuthenticationServiceProtocol.swift */; }; 56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */; }; 5705511EBE083295EF98F998 /* FrequentlyUsedEmoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A2074C0449B83D5858BD2D7 /* FrequentlyUsedEmoji.swift */; }; @@ -627,6 +627,7 @@ 6CD61FAF03E8986523C2ABB8 /* StartChatScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3005886F00029F058DB62BE /* StartChatScreenCoordinator.swift */; }; 6DC8E43BA04AC2AC4EB2EB97 /* AnalyticsPromptScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */; }; 6E03A710799E6C65C0AB36BC /* TargetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D829FD8958376614504B18 /* TargetConfiguration.swift */; }; + 6E0C68918BEC5D27A4830BA6 /* PlaybackSpeedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDBB8E5436E1BE0D6814BB7D /* PlaybackSpeedButton.swift */; }; 6E391F7F628D984AF44385D9 /* RoomAttachmentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 128501375217576AF0FE3E92 /* RoomAttachmentPicker.swift */; }; 6E44638FDF7D4B0F80EFA7EA /* TraceLogPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7149BDDE47F8AD104E644E2 /* TraceLogPack.swift */; }; 6E47D126DD7585E8F8237CE7 /* LoadableAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */; }; @@ -804,6 +805,7 @@ 8B408C574E35E1C9B43A50CE /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */; }; 8B41D0357B91CD3B6F6A3BCA /* EmoteRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */; }; 8B76191B9DDD1AC90A6E3A35 /* MediaFileHandleProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */; }; + 8B9C2890B6DD160A0662861E /* AudioPlaybackSpeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78B4E56DBFFD4A7A39D10F5 /* AudioPlaybackSpeed.swift */; }; 8BC8EF6705A78946C1F22891 /* SoftLogoutScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71A7D4DDEEE5D2CA0C8D63CD /* SoftLogoutScreen.swift */; }; 8BD22815DC34D7F9E9C1F2FE /* PillUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C537DE821FED94D23467B6C4 /* PillUtilities.swift */; }; 8C050A8012E6078BEAEF5BC8 /* PillTextAttachmentData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 913C8E13B8B602C7B6C0C4AE /* PillTextAttachmentData.swift */; }; @@ -1205,6 +1207,7 @@ D26093BB80B69092B0E9AC7C /* PinnedItemsIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E66763BD54A3A1D9C6E6F2F1 /* PinnedItemsIndicatorView.swift */; }; D2825E013A8ECFB66D9A1DE6 /* RoomChangeRolesScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */; }; D29E999538E5ABC00E1668F8 /* ElementNavigationStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03AEAA2F66E796C365EFD58 /* ElementNavigationStack.swift */; }; + D2CBC380FEBCBF29263B8446 /* AudioPlaybackSpeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78B4E56DBFFD4A7A39D10F5 /* AudioPlaybackSpeed.swift */; }; D2D70B5DB1A5E4AF0CD88330 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 033DB41C51865A2E83174E87 /* target.yml */; }; D304343515CE0464C5089537 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BD5523BDEDB247E29228476 /* AppSettings.swift */; }; D31B34B3902BC597593F3ABB /* preview_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 200626E8353AB2729444F991 /* preview_image.jpg */; }; @@ -2558,7 +2561,6 @@ B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenCoordinator.swift; sourceTree = ""; }; B81B6170DB690013CEB646F4 /* MapLibreModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLibreModels.swift; sourceTree = ""; }; B8516302ACCA94A0E680AB3B /* VoiceMessageButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageButton.swift; sourceTree = ""; }; - HW13ISECOFUYATOTX2RU7GDG /* PlaybackSpeedButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackSpeedButton.swift; sourceTree = ""; }; B858A61F2A570DFB8DE570A7 /* AggregratedReaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AggregratedReaction.swift; sourceTree = ""; }; B88CE0A058727BC68EEEC6B6 /* ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtension.entitlements; sourceTree = ""; }; B8A3B7637DDBD6AA97AC2545 /* CameraPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraPicker.swift; sourceTree = ""; }; @@ -2580,6 +2582,7 @@ BC8AA23D4F37CC26564F63C5 /* LayoutMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutMocks.swift; sourceTree = ""; }; BCDA016D05107DED3B9495CB /* TimelineItemDebugView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemDebugView.swift; sourceTree = ""; }; BD5480F03306234FC086E93B /* HomeScreenNewSoundBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenNewSoundBanner.swift; sourceTree = ""; }; + BDBB8E5436E1BE0D6814BB7D /* PlaybackSpeedButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackSpeedButton.swift; sourceTree = ""; }; BDE3EDEA7E64D68FEB828F83 /* SpaceSettingsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceSettingsFlowCoordinator.swift; sourceTree = ""; }; BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNNotificationContent.swift; sourceTree = ""; }; BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemReplyDetails.swift; sourceTree = ""; }; @@ -2894,6 +2897,7 @@ F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModel.swift; sourceTree = ""; }; F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = ""; }; F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreen.swift; sourceTree = ""; }; + F78B4E56DBFFD4A7A39D10F5 /* AudioPlaybackSpeed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlaybackSpeed.swift; sourceTree = ""; }; F7E247E29C7A0E421DB839D7 /* RoomPowerLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevel.swift; sourceTree = ""; }; F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = ""; }; F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionScreenTests.swift; sourceTree = ""; }; @@ -5601,7 +5605,7 @@ isa = PBXGroup; children = ( AD0FF64B0E6470F66F42E182 /* EstimatedWaveformView.swift */, - HW13ISECOFUYATOTX2RU7GDG /* PlaybackSpeedButton.swift */, + BDBB8E5436E1BE0D6814BB7D /* PlaybackSpeedButton.swift */, B8516302ACCA94A0E680AB3B /* VoiceMessageButton.swift */, FB9EABCA9348DFA27439A809 /* WaveformCursorView.swift */, BFEE91FB8ABB5F5884B6D940 /* WaveformInteractionModifier.swift */, @@ -6275,6 +6279,7 @@ 353024006CB726E9F9187B3A /* AnalyticsConsentState.swift */, 0FD22AEFFA20065494ED2333 /* AppAppearance.swift */, 7BD5523BDEDB247E29228476 /* AppSettings.swift */, + F78B4E56DBFFD4A7A39D10F5 /* AudioPlaybackSpeed.swift */, 0A2074C0449B83D5858BD2D7 /* FrequentlyUsedEmoji.swift */, 8A1F2AAA3F0F2B72D2FFE4D0 /* MapTilerConfiguration.swift */, E8D354D4232DED9649FD0FF4 /* OIDCConfiguration.swift */, @@ -7511,6 +7516,7 @@ 484202C5D50983442D24D061 /* AttributedString.swift in Sources */, CDCA8A559E098503DDE29477 /* AttributedStringBuilder.swift in Sources */, BA43D782BE85C7F5F20C624A /* AttributedStringBuilderProtocol.swift in Sources */, + D2CBC380FEBCBF29263B8446 /* AudioPlaybackSpeed.swift in Sources */, F255083E18CDBFDF7E640FB1 /* Avatars.swift in Sources */, A8E324E700E596E36B0A311B /* BootDetectionManager.swift in Sources */, 9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */, @@ -7745,6 +7751,7 @@ 88887E40301FF0543ED5B59F /* AppAppearance.swift in Sources */, 944EAB7BC2408B2C6570E722 /* AppHooks.swift in Sources */, 2CC3F27CD76DB00A747BEA6C /* AppSettings.swift in Sources */, + 56C18ACF91DD20463B242460 /* AudioPlaybackSpeed.swift in Sources */, 2F2906AE9BC3D0E79A6F98F8 /* Bundle.swift in Sources */, 88A87AA16CD93F57143623F8 /* ClientBuilderHook.swift in Sources */, D104B27C5DA0626B41CE78D3 /* CurrentValuePublisher.swift in Sources */, @@ -7877,6 +7884,7 @@ 2DA27D78560D5F79B917E163 /* AudioConverter.swift in Sources */, F3F38062C6CA21CF403C5C90 /* AudioConverterProtocol.swift in Sources */, 77E33FF0E4A50B555BF3A8AA /* AudioFileEventsTimelineView.swift in Sources */, + 8B9C2890B6DD160A0662861E /* AudioPlaybackSpeed.swift in Sources */, 46C9F8FE3810A04A005FE16B /* AudioPlayer.swift in Sources */, 086D01E79C8E8D3F004FAF21 /* AudioPlayerProtocol.swift in Sources */, 1471A080552631358D152C18 /* AudioPlayerState.swift in Sources */, @@ -8345,6 +8353,7 @@ 9D79B94493FB32249F7E472F /* PlaceholderAvatarImage.swift in Sources */, 1BA04D05EBC6646958B1BE60 /* PlaceholderScreenCoordinator.swift in Sources */, EF0D0155DD104C7A41A2EB0E /* PlainMentionBuilder.swift in Sources */, + 6E0C68918BEC5D27A4830BA6 /* PlaybackSpeedButton.swift in Sources */, B79E8AB83EBBDCD476D0362F /* PollFormScreen.swift in Sources */, 3DAD62988F072607441CB7A5 /* PollFormScreenCoordinator.swift in Sources */, 70B83D44043293B4B77440B9 /* PollFormScreenModels.swift in Sources */, @@ -8803,7 +8812,6 @@ 2CA61BB208CD82EBDB58CD13 /* VideoRoomTimelineView.swift in Sources */, 6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */, EED33AFD9334EFD7398707A6 /* VisualListItem.swift in Sources */, - ES17LAX66UIQ5OAE6L2BQQE4 /* PlaybackSpeedButton.swift in Sources */, 1318721F4E5F307586D98112 /* VoiceMessageButton.swift in Sources */, 4681820102DAC8BA586357D4 /* VoiceMessageCache.swift in Sources */, 4F2DF6138E87A4B8C2488CA3 /* VoiceMessageCacheProtocol.swift in Sources */, diff --git a/ElementX/Sources/Application/Settings/AppSettings.swift b/ElementX/Sources/Application/Settings/AppSettings.swift index 3768a9d74..2e8fc4fc1 100644 --- a/ElementX/Sources/Application/Settings/AppSettings.swift +++ b/ElementX/Sources/Application/Settings/AppSettings.swift @@ -362,8 +362,8 @@ final class AppSettings { @UserPreference(key: UserDefaultsKeys.optimizeMediaUploads, defaultValue: true, storageType: .userDefaults(store)) var optimizeMediaUploads - @UserPreference(key: UserDefaultsKeys.voiceMessagePlaybackSpeed, defaultValue: VoiceMessagePlaybackSpeed.default, storageType: .userDefaults(store)) - var voiceMessagePlaybackSpeed: VoiceMessagePlaybackSpeed + @UserPreference(key: UserDefaultsKeys.voiceMessagePlaybackSpeed, defaultValue: AudioPlaybackSpeed.default, storageType: .userDefaults(store)) + var voiceMessagePlaybackSpeed: AudioPlaybackSpeed /// Whether or not to show a warning on the media caption composer so the user knows /// that captions might not be visible to users who are using other Matrix clients. @@ -452,23 +452,3 @@ final class AppSettings { } extension AppSettings: CommonSettingsProtocol { } - -enum VoiceMessagePlaybackSpeed: Float, CaseIterable, Codable { - case `default` = 1.0 - case fast = 1.5 - case fastest = 2.0 - case slow = 0.5 - - var label: String { - switch self { - case .default, .fastest: - rawValue.formatted(.number.precision(.fractionLength(0))) + "×" - case .fast, .slow: - rawValue.formatted(.number.precision(.fractionLength(1))) + "×" - } - } - - var placeholder: String { - 0.0.formatted(.number.precision(.fractionLength(1))) + "×" - } -} diff --git a/ElementX/Sources/Application/Settings/AudioPlaybackSpeed.swift b/ElementX/Sources/Application/Settings/AudioPlaybackSpeed.swift new file mode 100644 index 000000000..27f123613 --- /dev/null +++ b/ElementX/Sources/Application/Settings/AudioPlaybackSpeed.swift @@ -0,0 +1,33 @@ +// +// Copyright 2026 Element Creations Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. +// Please see LICENSE files in the repository root for full details. +// + +enum AudioPlaybackSpeed: Float, CaseIterable, Codable { + case `default` = 1.0 + case fast = 1.5 + case fastest = 2.0 + case slow = 0.5 + + var label: String { + switch self { + case .default, .fastest: + rawValue.formatted(.number.precision(.fractionLength(0))) + "×" + case .fast, .slow: + rawValue.formatted(.number.precision(.fractionLength(1))) + "×" + } + } + + var placeholder: String { + 0.0.formatted(.number.precision(.fractionLength(1))) + "×" + } + + var next: Self { + guard let index = Self.allCases.firstIndex(of: self) else { + return .default + } + return Self.allCases[(index + 1) % Self.allCases.count] + } +} diff --git a/ElementX/Sources/Other/VoiceMessage/PlaybackSpeedButton.swift b/ElementX/Sources/Other/VoiceMessage/PlaybackSpeedButton.swift index ffb83c47b..7eb65738c 100644 --- a/ElementX/Sources/Other/VoiceMessage/PlaybackSpeedButton.swift +++ b/ElementX/Sources/Other/VoiceMessage/PlaybackSpeedButton.swift @@ -8,7 +8,7 @@ import SwiftUI struct PlaybackSpeedButton: View { - let speed: VoiceMessagePlaybackSpeed + let speed: AudioPlaybackSpeed let onTap: () -> Void var body: some View { @@ -35,7 +35,7 @@ struct PlaybackSpeedButton: View { struct PlaybackSpeedButton_Previews: PreviewProvider, TestablePreview { static var previews: some View { HStack(spacing: 8) { - ForEach(VoiceMessagePlaybackSpeed.allCases, id: \.self) { speed in + ForEach(AudioPlaybackSpeed.allCases, id: \.self) { speed in PlaybackSpeedButton(speed: speed) { } } } diff --git a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift index aa919070e..414890362 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift @@ -419,15 +419,7 @@ class TimelineInteractionHandler { // MARK: Audio Playback func changePlaybackSpeed(for itemID: TimelineItemIdentifier) { - let availableSpeeds = VoiceMessagePlaybackSpeed.allCases - guard let currentIndex = availableSpeeds.firstIndex(of: appSettings.voiceMessagePlaybackSpeed) else { - appSettings.voiceMessagePlaybackSpeed = .default - audioPlayerState(for: itemID)?.setPlaybackSpeed(VoiceMessagePlaybackSpeed.default) - return - } - - let nextIndex = (currentIndex + 1) % availableSpeeds.count - let nextSpeed = availableSpeeds[nextIndex] + let nextSpeed = appSettings.voiceMessagePlaybackSpeed.next appSettings.voiceMessagePlaybackSpeed = nextSpeed audioPlayerState(for: itemID)?.setPlaybackSpeed(nextSpeed) } diff --git a/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift b/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift index 3272d28ed..317d67809 100644 --- a/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift +++ b/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift @@ -36,7 +36,7 @@ class AudioPlayerState: ObservableObject, Identifiable { /// It's similar to `playbackState`, with the a difference: `.loading` /// updates are delayed by a fixed amount of time @Published private(set) var playerButtonPlaybackState: AudioPlayerPlaybackState - @Published private(set) var playbackSpeed: VoiceMessagePlaybackSpeed + @Published private(set) var playbackSpeed: AudioPlaybackSpeed private weak var audioPlayer: AudioPlayerProtocol? private var audioPlayerSubscription: AnyCancellable? @@ -63,8 +63,8 @@ class AudioPlayerState: ObservableObject, Identifiable { duration: Double, waveform: EstimatedWaveform? = nil, progress: Double = 0.0, - playbackSpeed: VoiceMessagePlaybackSpeed = .default, - playbackSpeedPublisher: AnyPublisher? = nil) { + playbackSpeed: AudioPlaybackSpeed = .default, + playbackSpeedPublisher: AnyPublisher? = nil) { self.id = id self.title = title self.duration = duration @@ -120,7 +120,7 @@ class AudioPlayerState: ObservableObject, Identifiable { playbackState = .error } - func setPlaybackSpeed(_ speed: VoiceMessagePlaybackSpeed) { + func setPlaybackSpeed(_ speed: AudioPlaybackSpeed) { playbackSpeed = speed audioPlayer?.setPlaybackSpeed(speed.rawValue) }