diff --git a/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/MiniPlayer.swift b/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/MiniPlayer.swift index e8c5aa8a5..875555c23 100644 --- a/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/MiniPlayer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/MiniPlayer.swift @@ -153,27 +153,29 @@ var audioCards: some View { ZStack { let textItems = self.audioController.textItems ?? [] - TabView(selection: $tabIndex) { - ForEach(0 ..< textItems.count, id: \.self) { id in - SpeechCard(id: id) - .tag(id) - } - } - .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) - .onChange(of: tabIndex, perform: { index in - if index != audioController.currentAudioIndex, index < (audioController.textItems?.count ?? 0) { - audioController.seek(toUtterance: index) - } - }) - .onChange(of: audioController.currentAudioIndex, perform: { index in - if index >= textItems.count { - return + if textItems.count > 0 { + TabView(selection: $tabIndex) { + ForEach(0 ..< textItems.count, id: \.self) { id in + SpeechCard(id: id) + .tag(id) + } } + .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) + .onChange(of: tabIndex, perform: { index in + if index != audioController.currentAudioIndex, index < (audioController.textItems?.count ?? 0) { + audioController.seek(toUtterance: index) + } + }) + .onChange(of: audioController.currentAudioIndex, perform: { index in + if index >= textItems.count { + return + } - if self.audioController.state != .reachedEnd { - tabIndex = index - } - }) + if self.audioController.state != .reachedEnd { + tabIndex = index + } + }) + } if audioController.state == .reachedEnd { // If we have reached the end display a replay button with an overlay behind @@ -279,7 +281,7 @@ Group { ScrubberView(value: $audioController.timeElapsed, - minValue: 0, maxValue: self.audioController.duration, + maxValue: $audioController.duration, onEditingChanged: { scrubStarted in if scrubStarted { self.audioController.scrubState = .scrubStarted @@ -359,6 +361,12 @@ .shadow(color: expanded ? .clear : .gray.opacity(0.33), radius: 8, x: 0, y: 4) .mask(Rectangle().padding(.top, -20)) ) + .onChange(of: audioController.state, perform: { state in + // Reset the tabIndex when we load a new audio item + if state == .loading { + tabIndex = 0 + } + }) .onTapGesture { withAnimation(.easeIn(duration: 0.08)) { expanded = true } }.sheet(isPresented: $showVoiceSheet) { @@ -432,7 +440,7 @@ Button(action: { audioController.currentVoice = voice.key self.showVoiceSheet = false - }) { + }, label: { HStack { Text(voice.name) @@ -443,8 +451,7 @@ } } .contentShape(Rectangle()) - } - .buttonStyle(PlainButtonStyle()) + }).buttonStyle(PlainButtonStyle()) } } .padding(.top, 32) @@ -453,11 +460,11 @@ } .navigationBarTitle("Voice") .navigationBarTitleDisplayMode(.inline) - .navigationBarItems(leading: Button(action: { self.showVoiceSheet = false }) { + .navigationBarItems(leading: Button(action: { self.showVoiceSheet = false }, label: { Image(systemName: "chevron.backward") .font(.appNavbarIcon) .tint(.appGrayTextContrast) - }) + })) } } diff --git a/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/ScrubberView.swift b/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/ScrubberView.swift index a8ddde418..e551eca40 100644 --- a/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/ScrubberView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/ScrubberView.swift @@ -7,20 +7,18 @@ typealias UIViewType = UISlider @Binding var value: Double - var minValue: Double - var maxValue: Double + @Binding var maxValue: Double var onEditingChanged: (Bool) -> Void - init(value: Binding, minValue: Double, maxValue: Double, onEditingChanged: @escaping (Bool) -> Void) { + init(value: Binding, maxValue: Binding, onEditingChanged: @escaping (Bool) -> Void) { self._value = value - self.minValue = minValue - self.maxValue = maxValue + self._maxValue = maxValue self.onEditingChanged = onEditingChanged } func makeUIView(context: Context) -> UISlider { let slider = UISlider(frame: .zero) - slider.maximumValue = Float(minValue) + slider.minimumValue = Float(0.0) slider.maximumValue = Float(maxValue) let tintColor = UIColor(Color.appCtaYellow) @@ -43,6 +41,7 @@ func updateUIView(_ uiView: UISlider, context _: Context) { uiView.value = Float(value) + uiView.maximumValue = Float(maxValue) } func makeCoordinator() -> Coordinator { diff --git a/apple/OmnivoreKit/Sources/Services/AudioSession/AudioController.swift b/apple/OmnivoreKit/Sources/Services/AudioSession/AudioController.swift index e1598bc75..fdb4a686a 100644 --- a/apple/OmnivoreKit/Sources/Services/AudioSession/AudioController.swift +++ b/apple/OmnivoreKit/Sources/Services/AudioSession/AudioController.swift @@ -207,6 +207,8 @@ @Published public var durationString: String? @Published public var voiceList: [(name: String, key: String, category: VoiceCategory, selected: Bool)]? + @Published public var textItems: [String]? + let dataService: DataService var timer: Timer? @@ -266,6 +268,7 @@ timeElapsed = 0 duration = 1 durations = nil + currentAudioIndex = 0 if let stoppedId = stoppedId { EventTracker.track( @@ -480,8 +483,6 @@ let body: String } - public var textItems: [String]? - func setTextItems() { if let document = self.document { textItems = document.utterances.map { utterance in @@ -491,6 +492,7 @@ } return "" } + currentAudioIndex = 0 } else { textItems = nil } @@ -940,7 +942,7 @@ let str = String(decoding: data, as: UTF8.self) print("result speech file: ", str) - let document = try? JSONDecoder().decode(SpeechDocument.self, from: data) + document = try? JSONDecoder().decode(SpeechDocument.self, from: data) // Cache the file - if it exists if let document = document {