uttrflow / uttrflow/uttrflow-swift

The AI suggestion ghost is placed for left-to-right text only: in Arabic or Hebrew it is anchored on the wrong side of the caret and drawn over what was typed

Open
#616 0 comments 0 reactions 0 assignees View on GitHub
area:ai-suggestions bug help wanted P2
Dominant language
Swift
Stars
4
Forks
17
Avg merge
3h 32m
Merged PRs (30d)
277

Description

## What happens

Every step from caret to panel assumes the text runs left to right.

1. **The caret is taken from the wrong edge of the previous character.** `FocusedFieldReader.caret` (`Sources/UttrflowContext/FocusedFieldReader+System.swift:205-211`) places the caret at the previous character's right edge:

```swift
// The caret sits at the trailing edge of the glyph before it…
return CGRect(x: before.maxX, y: before.minY, width: 0, height: before.height)
```

For a right-to-left run, the logically previous character sits to the **right** of the caret, so its trailing edge is `minX`. The fallback at `:213-214` (`at.minX` of the next character) has the same assumption mirrored.

2. **The ghost is drawn to the right of that point.** `SuggestionGeometry.anchor` (`Sources/UttrflowContext/SuggestionGeometry.swift:35-40`) uses `x: caret.maxX`. `availableWidth` (`:44-49`) measures room from the caret to the field's or screen's **right** edge.

3. **Nothing asks which way the line runs.** Neither the reader nor the geometry reads direction:

```
$ git grep -n -i "rightToLeft\|writingDirection\|bidi" -- Sources/UttrflowContext Sources/UttrflowPredict Sources/Uttrflow/Suggestion
(no output)
```

`SuggestionView` lays out its text left to right as well.

For a user typing Arabic, Hebrew, Persian or Urdu, the ghost starts one character to the right of the real caret and extends rightwards, which is back over the words already typed. Its right-edge clamp is measured on the wrong side, so a caret near the field's left edge (where RTL lines end) still gets a full-width ghost. Mixed lines, such as an RTL sentence containing a Latin product code, have both problems at the run boundary.

No gate stops suggestions for these scripts: `Quieting` (`Sources/UttrflowPredict/Quieting.swift:31-63`) has no script or direction reason.

## Why it matters

Ghost text drawn over what someone just typed makes the field unreadable, and Tab would then accept a continuation the user could not read. Non-English users are the ones who get it.

## How to reproduce

Needs a real RTL field, so `help wanted`:

1. Add an Arabic or Hebrew input source and type a sentence in a plain multi-line text editor window. Pause at the end of the line.
2. With AI suggestions on, note where the ghost is drawn relative to the caret.
3. Run `uttrflow-dev probe surface` in the same field and report the caret rectangle it reads, alongside a screenshot description of where the real caret is.

## Acceptance criteria

- The reader reports a direction for the run at the caret, from `kAXAttributedStringForRangeParameterizedAttribute`'s paragraph style or by comparing the bounds of the previous and next characters, and takes the caret from the leading edge that direction implies.
- `SuggestionGeometry` anchors the ghost on the side the text grows towards, measures room towards that field or screen edge, and has tests for an RTL caret near either edge.
- `SuggestionView` lays out RTL text right to left. Where direction cannot be determined, the turn is quiet with a named reason rather than drawn on a guess.

Contributor guide

Open the contributing guide

Research direction

Start by reading FocusedFieldReader+System.swift at lines 205-214, then trace SuggestionGeometry.swift lines 35-49 and the SuggestionView layout. Reproduce an RTL case with an Arabic or Hebrew input source and run `uttrflow-dev probe surface` to compare the reported caret with the real caret. Done means RTL and mixed-direction suggestions anchor and clamp correctly, have geometry coverage near both edges, and remain quiet when direction is unavailable.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, swift
Domain
accessibility, desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.