Skip to content

[AI-3828] app: Show the text cursor over chat prose - #1644

Merged
nortonandreev merged 2 commits into
mainfrom
norton/ai-3828-ibeam
Oct 21, 2026
Merged

nortonandreev merged 2 commits into
mainfrom
norton/ai-3828-ibeam

Conversation

@nortonandreev

@nortonandreev nortonandreev commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

AI-3828 — no GitHub issue

What & why

The pointer is an I-beam over chat text and a hand over a link or an openable image. A bare image keeps the arrow.

Where to look

The cursor follows what is under the pointer. A bare image sets the arrow itself, because an unset cursor inherits the viewer's I-beam.

Verification

dotnet run --project test/Capacitor.App.Tests.Unit/Capacitor.App.Tests.Unit.csproj -- --treenode-filter "/*/*/ChatCursorTests/*" — 2 passed.

  • Hover message text: I-beam.
  • Hover a link: hand.
  • Hover a bare image: arrow.
  • Hover a linked image: hand.

Summary by CodeRabbit

  • Enhancements

    • Cursor behavior now reflects content under the pointer: selectable text uses an I-beam cursor, links and linked images use a hand cursor, and standalone images use an arrow cursor.
    • Existing tooltip updates remain available when moving across content.
  • Tests

    • Added coverage for cursor behavior across prose, links, standalone images, and linked images.

@nortonandreev nortonandreev self-assigned this Oct 19, 2026
@linear-code

linear-code Bot commented Oct 19, 2026

Copy link
Copy Markdown

AI-3828

@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 0d5fb3ff-9ff9-439c-9f9e-d4dceda92c95
📥 Commits

Reviewing files that changed from the base of the PR and between 5b91187 and b528dd9.

📒 Files selected for processing: 3
  • src/Capacitor.App/Views/MarkdownImage.cs
  • src/Capacitor.App/Views/MarkdownView.cs
  • test/Capacitor.App.Tests.Unit/ChatCursorTests.cs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.

📝 Walkthrough

MarkdownView now selects cursors for prose, links, linked images, and bare images. MarkdownImage assigns hand or arrow cursors. Avalonia UI tests cover these pointer states.

Changes: Markdown cursor selection

Layer / File(s) Summary
Pointer-based cursor selection
src/Capacitor.App/Views/MarkdownView.cs, src/Capacitor.App/Views/MarkdownImage.cs, test/Capacitor.App.Tests.Unit/ChatCursorTests.cs
MarkdownView caches cursors and selects I-beam, hand, or arrow based on the pointer target. MarkdownImage assigns hand for linked images and arrow for bare images. Avalonia tests verify all cursor states and retain tooltip processing.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix

Suggested reviewers: realtonyyoung

Merge Risk: ⚪ Minimal · up to b528d

No actionable merge-blocking risk is established for this cursor-selection change.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly describes the primary change: showing the text cursor over chat prose. It does not mention link and image cursor behavior, but the title does not need to cover every detail.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

The viewer cursor is the hand on a link and the text cursor on the rest of the message.
@nortonandreev
nortonandreev marked this pull request as ready for review October 21, 2026 09:46
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Show an I-beam over chat prose and a hand over links

🐞 Bug fix 🧪 Tests 🕐 10-20 Minutes

Grey Divider

AI Description

• Show an I-beam over selectable markdown prose while retaining the hand cursor on links.
• Add a headless hover test for both cursor states.
Diagram

graph TD
  move["Pointer move"] --> host["MarkdownView"] --> lookup["Hyperlink lookup"] --> decision{"Link found?"}
  decision -->|Yes| hand["Hand cursor"] --> viewer["MarkdownViewer"]
  decision -->|No| ibeam["I-beam cursor"] --> viewer
Loading
High-Level Assessment

Keep cursor selection in the existing pointer-move handler, which already locates hyperlinks for tooltips. Relying on the viewer’s default cursor would leave prose with its current arrow cursor.

Files changed (2) +40 / -2

Bug fix (1) +7 / -2
MarkdownView.csSelect the markdown cursor by hyperlink hover +7/-2

Select the markdown cursor by hyperlink hover

• Sets the embedded viewer’s cursor to an I-beam for non-link content and a hand for hyperlinks. Reuses the existing hyperlink lookup used to set link tooltips.

src/Capacitor.App/Views/MarkdownView.cs

Tests (1) +33 / -0
ChatCursorTests.csTest prose and link cursor states +33/-0

Test prose and link cursor states

• Adds a headless hover test that moves over paragraph text and a link, asserting the viewer’s I-beam and hand cursors respectively.

test/Capacitor.App.Tests.Unit/ChatCursorTests.cs

@qodo-code-review

qodo-code-review Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Display-only images show a text cursor ✓ Resolved
Description
OnPointerMoved assigns the I-beam whenever FindHyperlinkAt returns null, without checking
whether the pointer is over a display-only image. In GitHub-flavoured markdown, bare images have no
link target or local cursor, so hovering their pictures or labels inherits the viewer’s text cursor
even though those elements are not selectable prose.
Code

src/Capacitor.App/Views/MarkdownView.cs[95]

+        _viewer.Cursor = link is null ? IBeamCursor : HandCursor;
Relevance

●●● Strong

Recent Markdown image hover precedent was accepted, supporting cursor and target handling for
image-only content.

PR-#1646
PR-#1681

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new assignment selects I-beam for every position without a hyperlink. The renderer creates
display-only images without a target, and MarkdownImage sets its own cursor only when a target
exists; its transparent background makes the image box hit-testable.

src/Capacitor.App/Views/MarkdownView.cs[90-102]
src/Capacitor.App/Views/KcapMarkdownExtension.cs[46-51]
src/Capacitor.App/Views/MarkdownImage.cs[49-54]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Display-only markdown images inherit the viewer’s I-beam cursor even though they are not selectable text.

## Fix Focus Areas
- src/Capacitor.App/Views/MarkdownView.cs[91-95]
- src/Capacitor.App/Views/MarkdownImage.cs[49-54]

## Recommended Fix
Distinguish display-only images from prose when choosing the cursor. Keep the default arrow over images without a target, while preserving the hand over openable images and links.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

2. Avalonia tests can run concurrently 📘 Rule violation ▣ Testability
Description
ChatCursorTests uses [NotInParallel("AvaloniaSession")] instead of the required bare
[NotInParallel] attribute. The grouped attribute does not satisfy the rule's required annotation
form for tests that manipulate the shared Avalonia session, so concurrent tests can still interfere
through shared UI state.
Code

test/Capacitor.App.Tests.Unit/ChatCursorTests.cs[R11-12]

+    [Test]
+    [NotInParallel("AvaloniaSession")]
Relevance

● Weak

The cited bare-attribute rule targets console capture; Avalonia tests conventionally use the
shared-session group key.

PR-#858
PR-#751

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The test declares a parameterized [NotInParallel("AvaloniaSession")] attribute on the added test
method. Compliance rule 2741710 requires every relevant test to use exactly a bare [NotInParallel]
attribute with no constructor arguments.

Rule 2741710: Annotate console-output-capturing tests with bare [NotInParallel]
test/Capacitor.App.Tests.Unit/ChatCursorTests.cs[11-12]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`ChatCursorTests` uses `[NotInParallel("AvaloniaSession")]`, but console/UI-sensitive tests must use exactly the bare `[NotInParallel]` attribute without a group key or other arguments.

## Fix Focus Areas
- test/Capacitor.App.Tests.Unit/ChatCursorTests.cs[11-12]

## Recommended Fix
Replace `[NotInParallel("AvaloniaSession")]` with `[NotInParallel]` on `ChatCursorTests`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗


Grey Divider

Context sources
❌ Tickets: failed to load — Ticket collection could not establish complete evidence
✅ Compliance rules (platform): 59 rules
✅ Cross-repo context — repo relationships
Review mode: Auto: ⚖️ Balanced: Localized UI behavior change with runtime cursor and event-routing logic.

Grey Divider

Tip of the day
💡 Did you know, you can start a comment with 'qodo' or '@qodo' to chat about any finding

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/Capacitor.App/Views/MarkdownView.cs Resolved
coderabbitai[bot]
coderabbitai Bot previously approved these changes Oct 21, 2026
Cursor inherits, so the viewer's I-beam reached a bare image that never set one.
@nortonandreev

Copy link
Copy Markdown
Contributor Author

ChatCursorTests uses [NotInParallel("AvaloniaSession")] instead of the required bare [NotInParallel].

Not addressing: that rule is for tests that capture console output. This test does not. Avalonia tests exclude each other with the AvaloniaSession key. A bare attribute would take the lock for the whole assembly.

@nortonandreev
nortonandreev merged commit 81a1394 into main Oct 21, 2026
13 checks passed
@nortonandreev
nortonandreev deleted the norton/ai-3828-ibeam branch October 21, 2026 11:36
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.

1 participant