@ -202,7 +202,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    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 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        audioPlayer. wrappedValue ? . stop  ( ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        stopAudio ( ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   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 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            . 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 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        //   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  [ 
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -957,6 +967,12 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    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 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            let  attachment :  Attachment  =  viewModel . attachments ? . first , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            let  originalFilePath :  String  =  attachment . originalFilePath , 
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -1010,6 +1026,12 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    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 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        guard  viewModel . id  = =  currentPlayingInteraction . wrappedValue  else  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            playOrPauseAudio ( for :  viewModel ) 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -1027,12 +1049,18 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    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 ( )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        // /   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 ( ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        currentPlayingInteraction . mutate  {  $0  =  nil  } 
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -1088,13 +1116,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        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 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        currentPlayingInteraction . mutate  {  $0  =  nil  } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        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 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        stopAudio ( ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        //   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 
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -1121,7 +1143,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                playbackRate :  1 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        currentPlayingInteraction. mutate  {  $0  =  nil  }  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        stopAudio( )  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        playbackInfo . mutate  {  $0 [ interactionId ]  =  updatedPlaybackInfo  } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        updatedPlaybackInfo ? . updateCallback ( updatedPlaybackInfo ,  AttachmentError . invalidData ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    }