@ -202,7 +202,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
deinit {
deinit {
// S t o p a n y a u d i o p l a y i n g w h e n l e a v i n g t h e s c r e e n
// S t o p a n y a u d i o p l a y i n g w h e n l e a v i n g t h e s c r e e n
audioPlayer. wrappedValue ? . stop ( )
stopAudio ( )
}
}
// MARK: - T h r e a d D a t a
// MARK: - T h r e a d D a t a
@ -442,6 +442,16 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
. filter { ! $0 . cellType . isPostProcessed } // R e m o v e h e a d e r s a n d o t h e r
. filter { ! $0 . cellType . isPostProcessed } // R e m o v e h e a d e r s a n d o t h e r
. sorted { lhs , rhs -> Bool in lhs . timestampMs < rhs . timestampMs }
. sorted { lhs , rhs -> Bool in lhs . timestampMs < rhs . timestampMs }
// I f w e a r e c u r r e n t l y p l a y i n g a v o i c e m e s s a g e w e s h o u l d m a k e s u r e i t h a s n ' t b e e n d e l e t e d a n d , i f
// i t h a s , w e s h o u l d s t o p p l a y i n g t h e a u d i o ( t h i s i s m o s t l y t o c a t c h t h e c a s e w h e r e a m e s s a g e i s
// d e l e t e d d u e t o a d i s a p p e a r i n g m e s s a g e s s e t t i n g )
if
let audioPlayingInteractionId : Int64 = currentPlayingInteraction . wrappedValue ,
! sortedData . contains ( where : { $0 . id = = audioPlayingInteractionId } )
{
self . stopAudio ( )
}
// W e l o a d m e s s a g e s f r o m n e w e s t t o o l d e s t s o h a v i n g a p a g e O f f s e t l a r g e r t h a n z e r o m e a n s
// W e l o a d m e s s a g e s f r o m n e w e s t t o o l d e s t s o h a v i n g a p a g e O f f s e t l a r g e r t h a n z e r o m e a n s
// t h e r e a r e n e w e r p a g e s t o l o a d
// t h e r e a r e n e w e r p a g e s t o l o a d
return [
return [
@ -957,6 +967,12 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
}
}
public func playOrPauseAudio ( for viewModel : MessageViewModel ) {
public func playOrPauseAudio ( for viewModel : MessageViewModel ) {
// / E n s u r e t h e ` O W S A u d i o P l a y e r ` l o g i c i s r u n o n t h e m a i n t h r e a d a s i t c a l l s ` M a i n A p p C o n t e x t . e n s u r e S l e e p B l o c k i n g `
// / m u s t r u n o n t h e m a i n t h r e a d ( a l s o t h e r e i s n o g u a r a n t e e t h a t ` A V A u d i o P l a y e r ` i s t h r e a d s a f e s o b e t t e r s a f e t h a n s o r r y )
guard Thread . isMainThread else {
return DispatchQueue . main . sync { [ weak self ] in self ? . playOrPauseAudio ( for : viewModel ) }
}
guard
guard
let attachment : Attachment = viewModel . attachments ? . first ,
let attachment : Attachment = viewModel . attachments ? . first ,
let originalFilePath : String = attachment . originalFilePath ,
let originalFilePath : String = attachment . originalFilePath ,
@ -1010,6 +1026,12 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
}
}
public func speedUpAudio ( for viewModel : MessageViewModel ) {
public func speedUpAudio ( for viewModel : MessageViewModel ) {
// / E n s u r e t h e ` O W S A u d i o P l a y e r ` l o g i c i s r u n o n t h e m a i n t h r e a d a s i t c a l l s ` M a i n A p p C o n t e x t . e n s u r e S l e e p B l o c k i n g `
// / m u s t r u n o n t h e m a i n t h r e a d ( a l s o t h e r e i s n o g u a r a n t e e t h a t ` A V A u d i o P l a y e r ` i s t h r e a d s a f e s o b e t t e r s a f e t h a n s o r r y )
guard Thread . isMainThread else {
return DispatchQueue . main . sync { [ weak self ] in self ? . speedUpAudio ( for : viewModel ) }
}
// I f w e a r e n ' t p l a y i n g t h e s p e c i f i e d i t e m t h e n j u s t s t a r t p l a y i n g i t
// I f w e a r e n ' t p l a y i n g t h e s p e c i f i e d i t e m t h e n j u s t s t a r t p l a y i n g i t
guard viewModel . id = = currentPlayingInteraction . wrappedValue else {
guard viewModel . id = = currentPlayingInteraction . wrappedValue else {
playOrPauseAudio ( for : viewModel )
playOrPauseAudio ( for : viewModel )
@ -1029,10 +1051,16 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
public func stopAudioIfNeeded ( for viewModel : MessageViewModel ) {
public func stopAudioIfNeeded ( for viewModel : MessageViewModel ) {
guard viewModel . id = = currentPlayingInteraction . wrappedValue else { return }
guard viewModel . id = = currentPlayingInteraction . wrappedValue else { return }
audioPlayer. wrappedValue ? . stop ( )
stopAudio ( )
}
}
public func stopAudio ( ) {
public func stopAudio ( ) {
// / E n s u r e t h e ` O W S A u d i o P l a y e r ` l o g i c i s r u n o n t h e m a i n t h r e a d a s i t c a l l s ` M a i n A p p C o n t e x t . e n s u r e S l e e p B l o c k i n g `
// / m u s t r u n o n t h e m a i n t h r e a d ( a l s o t h e r e i s n o g u a r a n t e e t h a t ` A V A u d i o P l a y e r ` i s t h r e a d s a f e s o b e t t e r s a f e t h a n s o r r y )
guard Thread . isMainThread else {
return DispatchQueue . main . sync { [ weak self ] in self ? . stopAudio ( ) }
}
audioPlayer . wrappedValue ? . stop ( )
audioPlayer . wrappedValue ? . stop ( )
currentPlayingInteraction . mutate { $0 = nil }
currentPlayingInteraction . mutate { $0 = nil }
@ -1088,13 +1116,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
updatedPlaybackInfo ? . updateCallback ( updatedPlaybackInfo , nil )
updatedPlaybackInfo ? . updateCallback ( updatedPlaybackInfo , nil )
// C l e a r o u t t h e c u r r e n t l y p l a y i n g r e c o r d
// C l e a r o u t t h e c u r r e n t l y p l a y i n g r e c o r d
currentPlayingInteraction . mutate { $0 = nil }
stopAudio ( )
audioPlayer . mutate {
// N o t e : W e c l e a r t h e d e l e g a t e a n d e x p l i c i t l y s e t t o n i l h e r e a s w h e n t h e O W S A u d i o P l a y e r
// g e t s d e a l l o c a t e d i t t r i g g e r s s t a t e c h a n g e s w h i c h c a u s e U I b u g s w h e n a u t o - p l a y i n g
$0 ? . delegate = nil
$0 = nil
}
// I f t h e n e x t i n t e r a c t i o n i s a n o t h e r v o i c e m e s s a g e t h e n a u t o p l a y i t
// I f t h e n e x t i n t e r a c t i o n i s a n o t h e r v o i c e m e s s a g e t h e n a u t o p l a y i t
guard
guard
@ -1121,7 +1143,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
playbackRate : 1
playbackRate : 1
)
)
currentPlayingInteraction. mutate { $0 = nil }
stopAudio( )
playbackInfo . mutate { $0 [ interactionId ] = updatedPlaybackInfo }
playbackInfo . mutate { $0 [ interactionId ] = updatedPlaybackInfo }
updatedPlaybackInfo ? . updateCallback ( updatedPlaybackInfo , AttachmentError . invalidData )
updatedPlaybackInfo ? . updateCallback ( updatedPlaybackInfo , AttachmentError . invalidData )
}
}