Skip to content

feat: Creating url with selected text in editor#2148

Open
killianmathias wants to merge 2 commits intomasterfrom
feat/copy-selected-link
Open

feat: Creating url with selected text in editor#2148
killianmathias wants to merge 2 commits intomasterfrom
feat/copy-selected-link

Conversation

@killianmathias
Copy link
Copy Markdown

No description provided.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR enables creating a link using the currently selected text in the rich HTML editor (prefilling the “Add link” alert based on whether the selection looks like a URL or a title).

Changes:

  • Switch swift-rich-html-editor dependency to a feature branch that exposes selection data.
  • Thread selected text state from ComposeMessageView into the editor and mobile formatting toolbar.
  • Update link alert presentation to an item-based flow and prefill AddLinkView from selection.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
Tuist/Package.swift Pins swift-rich-html-editor to a feature branch to access selection support.
Tuist/Package.resolved Updates resolved state to the branch + new revision.
Mail/Views/New Message/ComposeMessageView.swift Adds selectedText state and passes it into body + mobile toolbar.
Mail/Views/New Message/ComposeMessageBodyView.swift Passes selection into RichHTMLEditor and changes link alert presentation.
Mail/Views/New Message/ComposeEditor/Mobile/MobileFormattingToolbarView.swift Detects whether selected text is a URL/title and opens a prefilled link modal.
Mail/Views/New Message/ComposeEditor/Mobile/EditorMobileToolbarView.swift Plumbs selectedText binding down to the formatting toolbar.
Mail/Views/Alerts/AddLinkView.swift Accepts a SelectionLink to prefill title/url fields when adding a link.

Comment on lines +79 to +81
.onChange(of: selectedText) { newValue in
print("newValue: \(newValue)")
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

print("newValue: ...") will log every selection change in production builds (and can be very noisy). Please remove this debug logging or replace it with Logger behind a debug-only compilation flag if it’s still needed for troubleshooting.

Suggested change
.onChange(of: selectedText) { newValue in
print("newValue: \(newValue)")
}

Copilot uses AI. Check for mistakes.
.onEditorLoaded(perform: editorDidLoad)
.editorCSS(Self.customCSS)
.introspectEditor(perform: setupEditor)
.onJavaScriptFunctionFail(perform: reportJavaScriptError)
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

On macCatalyst (and macOS if applicable), the desktop toolbar toggles isShowingLinkAlert, but the view no longer presents an alert bound to that state (it now presents isShowingLink). This makes the “insert link” action from EditorDesktopToolbarView stop working. Either restore a .mailCustomAlert(isPresented: $isShowingLinkAlert) for the desktop flow, or update the desktop action to set isShowingLink (e.g., .empty) and drive the same item-based alert.

Suggested change
.onJavaScriptFunctionFail(perform: reportJavaScriptError)
.onJavaScriptFunctionFail(perform: reportJavaScriptError)
.mailCustomAlert(isPresented: $isShowingLinkAlert) {
AddLinkView(selectionLink: .empty, actionHandler: didCreateLink)
}

Copilot uses AI. Check for mistakes.
}

struct MobileFormattingToolbarView: View {
@ModalState(context: ContextKeys.compose) private var isShowingLinkAlert = false
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

isShowingLinkAlert is declared but no longer used in this view (the link UI is now driven by isShowingLink). Please remove this unused state to avoid confusion and keep the modal state surface minimal.

Suggested change
@ModalState(context: ContextKeys.compose) private var isShowingLinkAlert = false

Copilot uses AI. Check for mistakes.
Comment on lines +95 to 97
.mailCustomAlert(item: $isShowingLink) { link in
AddLinkView(selectionLink: link, actionHandler: textAttributes.addLink)
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

The .mailCustomAlert(item: $isShowingLink) modifier is currently applied inside the ForEach for every toolbar button, which can lead to multiple identical alert presenters in the view tree. Prefer attaching the alert once to a stable parent container (e.g., the outer HStack/ScrollView) and keep the buttons responsible only for setting isShowingLink.

Copilot uses AI. Check for mistakes.
Comment on lines +143 to +149
if Regex(pattern: MobileFormattingToolbarView.urlRegex)?.numberOfMatches(in: selectedText) == 1 {
if let url = URL(string: selectedText) {
isShowingLink = .url(url)
}
} else {
isShowingLink = .title(selectedText)
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

If selectedText matches the URL regex but doesn’t include a scheme (e.g. www.example.com), URL(string:) returns nil and isShowingLink is never set—so tapping the link button appears to do nothing. Consider either normalizing the selection before building the URL (prepend https:// when needed, similar to AddLinkView.didTapPrimaryButton) or falling back to .title(selectedText) / .empty when URL parsing fails so the alert still opens.

Copilot uses AI. Check for mistakes.
Comment on lines +322 to +323
await attachmentsManager.processHTMLAttachments(htmlAttachments, draftContentManager:
draftContentManager)
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

This argument wrap introduces an awkward line break (draftContentManager: on one line and the value on the next), which hurts readability and looks like a formatting mistake. Please keep the label/value together (or wrap using standard Swift formatting) so future diffs stay clean.

Suggested change
await attachmentsManager.processHTMLAttachments(htmlAttachments, draftContentManager:
draftContentManager)
await attachmentsManager.processHTMLAttachments(
htmlAttachments,
draftContentManager: draftContentManager
)

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +44
enum SelectionLink: Identifiable {
case url(URL)
case title(String)
case empty

var id: String {
switch self {
case .url(let url):
return url.absoluteString
case .title(let string):
return string
case .empty:
return "empty"
}
}
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

SelectionLink is used by multiple views (AddLinkView, ComposeMessageBodyView, and this toolbar), but it’s declared inside MobileFormattingToolbarView.swift (under a Mobile-specific folder). Consider moving it to a shared location (e.g., alongside AddLinkView or in a small SelectionLink.swift model file) to avoid surprising cross-file dependencies and make reuse clearer.

Copilot uses AI. Check for mistakes.
Comment thread Tuist/Package.swift
.package(url: "https://github.com/Infomaniak/swift-concurrency", .upToNextMajor(from: "1.0.0")),
.package(url: "https://github.com/Infomaniak/swift-modal-presentation", .upToNextMajor(from: "1.1.0")),
.package(url: "https://github.com/Infomaniak/swift-rich-html-editor", .upToNextMajor(from: "3.2.0")),
.package(url: "https://github.com/Infomaniak/swift-rich-html-editor", branch: "feat/get-selection"),
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

The dependency on swift-rich-html-editor is now tracking a branch (feat/get-selection). Branch-based dependencies make builds non-reproducible and can change without a corresponding update in this repo; prefer pinning to a tagged version or at least a specific revision (e.g., .revision(...)) and updating back to a released version once the feature is merged upstream.

Suggested change
.package(url: "https://github.com/Infomaniak/swift-rich-html-editor", branch: "feat/get-selection"),
.package(
url: "https://github.com/Infomaniak/swift-rich-html-editor",
revision: "REPLACE_WITH_THE_APPROVED_COMMIT_SHA_FROM_FEAT_GET_SELECTION"
),

Copilot uses AI. Check for mistakes.
@sonarqubecloud
Copy link
Copy Markdown

@valentinperignon valentinperignon added this to the 1.12.0 milestone Apr 27, 2026
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