@ -185,6 +185,7 @@ final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableView
let approvalVC : UINavigationController = AttachmentApprovalViewController . wrappedInNavController (
threadId : strongSelf . viewModel . viewData [ indexPath . row ] . threadId ,
threadVariant : strongSelf . viewModel . viewData [ indexPath . row ] . threadVariant ,
attachments : attachments ,
approvalDelegate : strongSelf
)
@ -197,6 +198,7 @@ final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableView
_ attachmentApproval : AttachmentApprovalViewController ,
didApproveAttachments attachments : [ SignalAttachment ] ,
forThreadId threadId : String ,
threadVariant : SessionThread . Variant ,
messageText : String ? ,
using dependencies : Dependencies = Dependencies ( )
) {
@ -221,78 +223,111 @@ final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableView
ModalActivityIndicatorViewController . present ( fromViewController : shareNavController ! , canCancel : false , message : " vc_share_sending_message " . localized ( ) ) { activityIndicator in
Storage . resumeDatabaseAccess ( )
dependencies . storage
. writePublisher { db -> MessageSender . PreparedSendData in
guard
let threadVariant : SessionThread . Variant = try SessionThread
. filter ( id : threadId )
. select ( . variant )
. asRequest ( of : SessionThread . Variant . self )
. fetchOne ( db )
else { throw MessageSenderError . noThread }
// C r e a t e t h e i n t e r a c t i o n
let interaction : Interaction = try Interaction (
threadId : threadId ,
authorId : getUserHexEncodedPublicKey ( db ) ,
variant : . standardOutgoing ,
body : body ,
timestampMs : SnodeAPI . currentOffsetTimestampMs ( ) ,
hasMention : Interaction . isUserMentioned ( db , threadId : threadId , body : body ) ,
expiresInSeconds : try ? DisappearingMessagesConfiguration
. select ( . durationSeconds )
. filter ( id : threadId )
. filter ( DisappearingMessagesConfiguration . Columns . isEnabled = = true )
. asRequest ( of : TimeInterval . self )
. fetchOne ( db ) ,
linkPreviewUrl : ( isSharingUrl ? attachments . first ? . linkPreviewDraft ? . urlString : nil )
) . inserted ( db )
guard let interactionId : Int64 = interaction . id else {
throw StorageError . failedToSave
}
// I f t h e u s e r i s s h a r i n g a U r l , t h e r e i s a L i n k P r e v i e w a n d i t d o e s n ' t m a t c h a n e x i s t i n g
// o n e t h e n a d d i t n o w
if
isSharingUrl ,
let linkPreviewDraft : LinkPreviewDraft = attachments . first ? . linkPreviewDraft ,
( try ? interaction . linkPreview . isEmpty ( db ) ) = = true
{
try LinkPreview (
url : linkPreviewDraft . urlString ,
title : linkPreviewDraft . title ,
attachmentId : LinkPreview
. generateAttachmentIfPossible (
imageData : linkPreviewDraft . jpegImageData ,
mimeType : OWSMimeTypeImageJpeg
) ?
. inserted ( db )
. id
) . insert ( db )
// / W h e n w e p r e p a r e t h e m e s s a g e w e s e t t h e t i m e s t a m p t o b e t h e ` S n o d e A P I . c u r r e n t O f f s e t T i m e s t a m p M s ( ) `
// / b u t w o n ' t a c t u a l l y h a v e a v a l u e b e c a u s e t h e s h a r e e x t e n s i o n w o n ' t h a v e t a l k e d t o a s e r v i c e n o d e y e t w h i c h c a n c a u s e
// / i s s u e s w i t h D i s a p p e a r i n g M e s s a g e s , a s a r e s u l t w e n e e d t o e x p l i c i t l y ` g e t N e t w o r k T i m e ` i n o r d e r t o e n s u r e i t ' s a c c u r a t e
Just ( ( ) )
. setFailureType ( to : Error . self )
. flatMap { _ in
// W e m a y n o t h a v e s u f f i c i e n t s n o d e s , s o r a t h e r t h a n f a i l i n g w e t r y t o l o a d / f e t c h
// t h e m i f n e e d e d
guard ! SnodeAPI . hasCachedSnodesIncludingExpired ( ) else {
return Just ( ( ) )
. setFailureType ( to : Error . self )
. eraseToAnyPublisher ( )
}
// P r e p a r e a n y a t t a c h m e n t s
try Attachment . process (
db ,
data : Attachment . prepare ( attachments : finalAttachments ) ,
for : interactionId
)
// P r e p a r e t h e m e s s a g e s e n d d a t a
return try MessageSender
. preparedSendData (
db ,
interaction : interaction ,
threadId : threadId ,
threadVariant : threadVariant ,
return SnodeAPI . getSnodePool ( )
. map { _ in ( ) }
. eraseToAnyPublisher ( )
}
. subscribe ( on : DispatchQueue . global ( qos : . userInitiated ) )
. flatMap { _ in
SnodeAPI
. getSwarm (
for : {
switch threadVariant {
case . contact , . legacyGroup , . group : return threadId
case . community : return getUserHexEncodedPublicKey ( using : dependencies )
}
} ( ) ,
using : dependencies
)
. tryFlatMapWithRandomSnode { SnodeAPI . getNetworkTime ( from : $0 , using : dependencies ) }
. map { _ in ( ) }
. eraseToAnyPublisher ( )
}
. flatMap { _ in
dependencies . storage . writePublisher { db -> MessageSender . PreparedSendData in
guard
let threadVariant : SessionThread . Variant = try SessionThread
. filter ( id : threadId )
. select ( . variant )
. asRequest ( of : SessionThread . Variant . self )
. fetchOne ( db )
else { throw MessageSenderError . noThread }
// C r e a t e t h e i n t e r a c t i o n
let interaction : Interaction = try Interaction (
threadId : threadId ,
authorId : getUserHexEncodedPublicKey ( db ) ,
variant : . standardOutgoing ,
body : body ,
timestampMs : SnodeAPI . currentOffsetTimestampMs ( ) ,
hasMention : Interaction . isUserMentioned ( db , threadId : threadId , body : body ) ,
expiresInSeconds : try ? DisappearingMessagesConfiguration
. select ( . durationSeconds )
. filter ( id : threadId )
. filter ( DisappearingMessagesConfiguration . Columns . isEnabled = = true )
. asRequest ( of : TimeInterval . self )
. fetchOne ( db ) ,
linkPreviewUrl : ( isSharingUrl ? attachments . first ? . linkPreviewDraft ? . urlString : nil )
) . inserted ( db )
guard let interactionId : Int64 = interaction . id else {
throw StorageError . failedToSave
}
// I f t h e u s e r i s s h a r i n g a U r l , t h e r e i s a L i n k P r e v i e w a n d i t d o e s n ' t m a t c h a n e x i s t i n g
// o n e t h e n a d d i t n o w
if
isSharingUrl ,
let linkPreviewDraft : LinkPreviewDraft = attachments . first ? . linkPreviewDraft ,
( try ? interaction . linkPreview . isEmpty ( db ) ) = = true
{
try LinkPreview (
url : linkPreviewDraft . urlString ,
title : linkPreviewDraft . title ,
attachmentId : LinkPreview
. generateAttachmentIfPossible (
imageData : linkPreviewDraft . jpegImageData ,
mimeType : OWSMimeTypeImageJpeg
) ?
. inserted ( db )
. id
) . insert ( db )
}
// P r e p a r e a n y a t t a c h m e n t s
try Attachment . process (
db ,
data : Attachment . prepare ( attachments : finalAttachments ) ,
for : interactionId
)
// P r e p a r e t h e m e s s a g e s e n d d a t a
return try MessageSender
. preparedSendData (
db ,
interaction : interaction ,
threadId : threadId ,
threadVariant : threadVariant ,
using : dependencies
)
}
}
. subscribe ( on : DispatchQueue . global ( qos : . userInitiated ) )
. flatMap { MessageSender . performUploadsIfNeeded ( preparedSendData : $0 , using : dependencies ) }
. flatMap { MessageSender . sendImmediate ( data : $0 , using : dependencies ) }
. subscribe ( on : DispatchQueue . global ( qos : . userInitiated ) )
. receive ( on : DispatchQueue . main )
. sinkUntilComplete (
receiveCompletion : { [ weak self ] result in