Update invite copy and app icon, show invite preview in composer#541
Update invite copy and app icon, show invite preview in composer#541
Conversation
- Detect invite URLs when pasted/typed in message input - Show invite preview in attachments area with Convos icon - Send full invite URL as separate message before any text - Replace old icon assets with convosOrangeIcon throughout
How to use the Graphite Merge QueueAdd the label merge-queue to this PR to add it to the merge queue. You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
Claude finished @yewreeka's task —— View job Pull Request ReviewComprehensive review of the invite URL detection feature. OverviewThis PR successfully implements invite URL detection in the message composer. The implementation is clean and follows project conventions well. The feature detects invite URLs when pasted/typed, shows a preview in the attachments area, and sends the full URL as a separate message. Code Quality & Best Practices✅ Strengths
|
| detector?.enumerateMatches(in: trimmedText, options: [], range: range) { match, _, stop in | ||
| guard let match = match, | ||
| let url = match.url, | ||
| let matchRange = Range(match.range, in: trimmedText) else { |
There was a problem hiding this comment.
🟠 High Utilities & Extensions/InviteURLDetector.swift:27
matchRange is computed from trimmedText (line 27) but returned for use on the original text in removeInviteURL. When leading/trailing whitespace exists, these indices won't match, causing a crash. Consider computing the range relative to the original text instead.
| let matchRange = Range(match.range, in: trimmedText) else { | |
| let matchRange = Range(match.range, in: text) else { |
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file Convos/Utilities & Extensions/InviteURLDetector.swift around line 27:
`matchRange` is computed from `trimmedText` (line 27) but returned for use on the original `text` in `removeInviteURL`. When leading/trailing whitespace exists, these indices won't match, causing a crash. Consider computing the range relative to the original `text` instead.
Evidence trail:
Convos/Utilities & Extensions/InviteURLDetector.swift lines 15, 20, 27, 32 (at REVIEWED_COMMIT) - shows trimmedText creation and matchRange computed from trimmedText.
Convos/Conversation Detail/ConversationViewModel.swift lines 1215, 1219 (at REVIEWED_COMMIT) - shows detectInviteURL called with messageText, then removeInviteURL called with same messageText and the returned range.

Note
Add invite URL detection and attachment preview in the message composer
NSDataDetectorto find Convos invite URLs or raw invite codes in message text, returning the code, full URL, and character range.ConversationViewModel.checkForInviteURL()extracts any detected invite URL frommessageTextand stores it as pending invite state; the send button enables when a pending invite exists.messageWriter.send(text:afterPhoto:), followed by any remaining text or photo.MessagesInputViewrenders a removable chip preview for the pending invite alongside photo attachments, with a poof animation on removal.convosIcon/convosIconLargeimage assets withconvosOrangeIconacross share, QR, and invite preview views.📊 Macroscope summarized a72f154. 9 files reviewed, 10 issues evaluated, 7 issues filtered, 1 comment posted
🗂️ Filtered Issues
Convos/Conversation Detail/ConversationView.swift — 0 comments posted, 2 evaluated, 2 filtered
pendingInviteCode != nilto allow sending, but the actual send logic usespendingInviteURL. IfpendingInviteCodeis set butpendingInviteURLis nil (due to sync issues between these properties), the guard will pass allowing the send to proceed, but no invite will actually be sent. This could result in a user expecting an invite to be sent when only an empty message (or nothing) is sent. [ Low confidence ].onChange(of: viewModel.messageText)modifier callsviewModel.checkForInviteURL()on every keystroke. IfcheckForInviteURL()performs expensive operations (like regex matching or URL parsing) synchronously, this could cause UI lag during typing, especially for longer messages. [ Low confidence ]Convos/Conversation Detail/ConversationViewModel.swift — 0 comments posted, 3 evaluated, 1 filtered
sendButtonEnablednow returnstruewhenpendingInviteCode != nil, enabling the send button with only a pending invite code. However, there is no visible implementation in the provided code showing how the send action handles this case. If the send logic does not check for and processpendingInviteCode, pressing send with only a pending invite (no text, no photo) may result in a no-op or unexpected behavior. [ Low confidence ]Convos/Conversation Detail/Messages/Messages View Controller/View Controller/Cells/MessageInviteContainerView.swift — 0 comments posted, 1 evaluated, 1 filtered
"convosIconLarge"to"convosOrangeIcon". If theconvosOrangeIconasset does not exist in the asset catalog, SwiftUI'sImage(_:)initializer will silently fail and render an empty view, causing the placeholder to appear blank instead of showing the intended fallback icon. [ Low confidence ]Convos/Conversation Detail/Messages/MessagesView.swift — 0 comments posted, 2 evaluated, 2 filtered
pendingInviteCode != nilto allow sending, but the actual send logic usespendingInviteURL. If these two state variables can become inconsistent (e.g.,pendingInviteCodeis set butpendingInviteURLis nil), the send operation will pass the guard but silently send nothing when the user only has an invite pending (no text or attachment). [ Low confidence ]afterPhoto: nilinstead of usingphotoTrackingKey. This could cause the invite message to appear before the photo in the conversation, rather than maintaining the expected order where messages sent together appear in sequence. [ Skipped comment generation ]Convos/Utilities & Extensions/InviteURLDetector.swift — 1 comment posted, 2 evaluated, 1 filtered
isLikelyInviteCode(line 82:text.count >= 50) is performed onpotentialCodeafter asterisks are removed (line 41), which could cause valid invite codes containing asterisks to fail the length threshold check and not be recognized as invite codes. [ Low confidence ]