Skip to content

#5898 Quick Reply#5957

Closed
MarlowBrown wants to merge 9 commits intosignalapp:mainfrom
MarlowBrown:#5898-QuickReply
Closed

#5898 Quick Reply#5957
MarlowBrown wants to merge 9 commits intosignalapp:mainfrom
MarlowBrown:#5898-QuickReply

Conversation

@MarlowBrown
Copy link

First time contributor checklist

Contributor checklist

  • My commits are rebased on the latest main branch
  • My commits are in nice logical chunks
  • My contribution is fully baked and is ready to be merged as is
  • I have tested my contribution on these devices:
  • iPhone 16, iOS 18.2

Description

This pull request fixes #5898 by allowing users to see which message they quick replied to. Previously before this PR users were not able to see the message that they replied to by using quick reply in the Notification Content Extension. I tested this PR by performing this user requested feature to make sure that it functioned as laid out in the user issue ticket.

QuickReply.mov

Talon Brown added 5 commits February 1, 2025 19:30
… reply notification content extensions.

(cherry picked from commit 07026687dbf3214417992ee1c3a19e1da48d7a90)
(cherry picked from commit ac54c92cfd5decefdabe7cf6ea32095ed248e10a)
(cherry picked from commit 8a9bb25874edf688314f45e32e8a0e52b94fcbfa)
(cherry picked from commit f2b085294f4990e60000f902b1187ce444734509)
(cherry picked from commit 33db5b07b10644c62f6f3bc8185953fef52264c6)
@sashaweiss-signal
Copy link
Contributor

FWIW, there are a lot of changes in this diff that are unrelated to the meaningful change, which is to build and pass along a quoted reply model. Those changes (e.g., renaming methods, restructuring methods without functional change) make it harder to review the change and verify that it's correct/safe. Generally, it's easier for us to accept changes that only touch the required lines.

(cherry picked from commit c73f420f1ee491a92b1bd04310e9c87f6c4d6033)
@MarlowBrown
Copy link
Author

MarlowBrown commented Feb 5, 2025

I made those extra changes because it was pretty difficult to keep track of what indentation level that I was in, so I flattened out the nested calls. It makes it easier to read and modify in the future, but at a cost of more time to QA it.

@sashaweiss-signal
Copy link
Contributor

I understand, and I don't disagree that working with this code is tricky. At the same time, it's now difficult for me to verify that something subtle hasn't changed in the functionality. For example, there are now a lot of unnecessary calls to firstly that will result in a lot of unnecessary hopping between dispatch queues.

I'd appreciate if, now that we understand what the desired change is here, we could reset the refactoring and keep only the changes related to fetching and using a DraftQuotedReplyModel. That'll make it a lot easier for me to verify that the new code uses Promises appropriately.

@MarlowBrown
Copy link
Author

MarlowBrown commented Feb 6, 2025

Yeah, I can do that! I'll undo the renamings and the restructurings and focus just on the bits that need to change to still implement the feature. Since I now know how the final code turned out it should be easy to do. I'll go get to work on it!

Talon Brown added 2 commits February 6, 2025 18:39
(cherry picked from commit d02ce213bacdeb5e859c2178b39ece28f0a250fe)
…t needs to be changed.

(cherry picked from commit eb9cc8c14d445a2db5e0c1a7aadba6a68b0b1676)
@MarlowBrown
Copy link
Author

@sashaweiss-signal Just made the changes. Let me know what you think!

Comment on lines 123 to 127
}.then(on: DispatchQueue.global()) { (notificationMessage: NotificationMessage) -> Promise<(DraftQuotedReplyModel?, NotificationMessage)> in
return getDraftQuotedReplyModelTupleFromIncomingMessage(notificationMessage: notificationMessage)
}.then(on: DispatchQueue.global()) { (informationTuple: (draft: DraftQuotedReplyModel?, notificationMessage: NotificationMessage)) -> Promise<(DraftQuotedReplyModel.ForSending?, NotificationMessage)> in
return getDraftQuotedReplyModelForSendingTupleFromDraftAndIncomingMessage(optionalDraftModel: informationTuple.draft, notificationMessage: informationTuple.notificationMessage)
}.then(on: DispatchQueue.global()) { (informationTuple: (draft: DraftQuotedReplyModel.ForSending?, notificationMessage: NotificationMessage)) -> Promise<Void> in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need for these to be their own Promises. We can construct the reply inline here:

...
let thread = notificationMessage.thread
let interaction = notificationMessage.interaction

let draftQuotedReplyModelForSending = try SKEnvironment.shared.databaseStorageRef.read { tx -> DraftQuotedReplyModel.ForSending? in
  if
    let incomingMessage = interaction as? TSIncomingMessage,
    let draftQuotedReplyModel = DependenciesBridge.shared.quotedReplyManager.buildDraftQuotedReply(originalMessage: incomingMessage, tx: txasV2Read)
  {
    return try DependenciesBridge.shared.quotedReplyManager.prepareDraftForSending(draftQuotedReplyModel)
  }

  return nil
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC If you put DependenciesBridge.shared.quotedReplyManager.prepareDraftForSending inside of a SSKEnvironment.shared.databaseStorageRef.read or SSKEnvironment.shared.databaseStorageRef.write block it will cause a database reentrant error because prepareDraftForSending is also reading from the database.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, annoying. Then something like:

...
let thread = notificationMessage.thread
let interaction = notificationMessage.interaction

let draftQuotedReplyModel = try SKEnvironment.shared.databaseStorageRef.read { tx -> DraftQuotedReplyModel? in
  if let incomingMessage = interaction as? TSIncomingMessage {
    return DependenciesBridge.shared.quotedReplyManager.buildDraftQuotedReply(originalMessage: incomingMessage, tx: txasV2Read)
  }

  return nil
}

let draftQuotedReplyModelForSending = try draftQuotedReplyModel.map { try DependenciesBridge.shared.quotedReplyManager.prepareDraftForSending($0) }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you already did something similar, thanks.

(cherry picked from commit 5104770e25498869993428a39adeaea4b5ee91f9)
@sashaweiss-signal
Copy link
Contributor

Thanks for making this PR much easier to review. I'll work on getting it merged internally!

@sashaweiss-signal
Copy link
Contributor

This has been merged internally as 6268f7f80a, which should become public in a week or two with an upcoming release. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants