Skip to content

fix(mobile): keep diff code left-aligned in RTL interfaces - #6400

Merged
iscekic merged 1 commit into
mainfrom
kwf/explorer-pr-diff-expanded-the-diff-text-is-center-aligned-618e3-d46c
Sep 21, 2026
Merged

iscekic merged 1 commit into
mainfrom
kwf/explorer-pr-diff-expanded-the-diff-text-is-center-aligned-618e3-d46c

Conversation

@iscekic

@iscekic iscekic commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator

Changelog for users

  • In a right-to-left interface, diff code lines stay left-aligned, so a wrapped line's continuation starts under the first line's start.
  • Hunk headers keep their left-to-right order, so each sign stays with its number.
  • English and other left-to-right interfaces are unchanged.

Changelog for maintainers

  • The unified diff line's code Text now names its own left-to-right base direction through LTR_TEXT_DIRECTION.
  • Both side-by-side column code Texts name the same direction.
  • Hunk header rows in the unified and side-by-side views pass the same direction.
  • LTR_TEXT_DIRECTION sets direction for Android and writingDirection for iOS.
  • The direction sits on the code Text, not a wrapping View, so the diff gutter does not mirror.
  • Review hint: the caller style lands after the shared Text's RTL entry, so it wins when React Native flattens the style array.
  • Tests cover the direction on unified code, side-by-side code, and hunk headers, plus the RTL fallback for text with no direction of its own.

E2E proof

**[e1] Arabic (RTL) interface, light mode, phone: open PR iscekic/tax-report-generator #1 → Files tab → unified mode and find the README prerequisite bullet; the code - A Trading 212 account (when running…** — android emulator-5554: scripted scene reached the anchored Files pane and matched its assert, log line 'SCENE e1 OK'; e1.txt shows the prerequisite code TextView text="- A Trading 212 account (when running against --t212) or a prepared IBKR CSV export (when running against --ibkr`)" bounds="[0,1261][928,1405]" — left edge 0, matching the single-line code TextView bounds="[0,681][928,729]", 144 px tall (wrapped) with the '+ 11' gutter at [946,1261] on its right in the mirrored RTL row; the on-screen alignment/continuation appearance is the visual reviewer's call on e1.png.

[e1] Arabic (RTL) interface, light mode, phone: open PR iscekic/tax-report-generator #1 → Files tab → unified mode and find the README prerequisite bullet; the code `- A Trading 212 account (when running… — e2e-mobile-app/e1.png

[e2] Arabic RTL: hunk header above line 1 reads @@ -0,0 +1,82 @@ left to right — android emulator-5604: e2-scene.log line 1 'SCENE e2 OK'; line 22 'android.widget.TextView @@ -0,0 +1,82 @@ tappable [36,625][1044,664]' sits directly above the line-1 row (line 23) in the Arabic RTL Files diff with unified mode checked, each sign preceding its number; screenshot e2.png captured for the visual reviewer; zero UX defects.

[e2] Arabic RTL: hunk header above line 1 reads @@ -0,0 +1,82 @@ left to right — e2e-mobile-app/e2.png

[e3] same PR in side-by-side mode (wide/tablet layout), Arabic RTL — android emulator-5554: log 'SCENE e3 OK'; e3.txt shows resource-id="diff-mode-side-by-side" checked="true" (mode active) and the new-column prerequisite code TextView bounds="[0,1575][392,1911]" (left edge 0, wrapped tall in the narrow column); the tablet branch is unreachable on this 1080x2400 ~3x phone emulator (short-edge gate >=600dp), so it was forced by a temporary is-tablet.ts hardcode that was reverted (git status clean, UI hot-reloaded to unified); rows read 'الجديد فقط:' because the PR is pure-add (+82/-0) so the old column holds no code; alignment appearance is the visual…

[e3] same PR in side-by-side mode (wide/tablet layout), Arabic RTL — e2e-mobile-app/e3.png

[e4] English LTR: code still left-aligned, gutter on the left, hunk header unchanged — android emulator-5604: e4-scene.log line 1 'SCENE e4 OK'; line 22 shows the same header 'android.widget.TextView @@ -0,0 +1,82 @@ tappable [36,625][1044,664]' and line 24 shows the gutter 'android.widget.TextView + 1 tappable [80,681][133,729]' on the left with the code text at x=152 to its right (vs x=946 in the RTL run, e2-scene.log line 24); screenshot e4.png captured for the visual reviewer; zero UX defects.

[e4] English LTR: code still left-aligned, gutter on the left, hunk header unchanged — e2e-mobile-app/e4.png

E2E proof — log excerpts

[e1] Arabic (RTL) interface, light mode, phone: PR iscekic/tax-report-generator  -> pass :: android emulator-5554: scripted scene reached the anchored Files pane and matched its assert, log line 'SCENE e1 OK'; e1.txt shows the prerequisite code TextView text="- A Trading 212 account (when running against `--t212`) or a prepared IBKR CSV export (when running against `--ibkr`)" bounds="[0,1261][928,1405]" — left edge 0, matching the single-line code TextView bounds="[0,681][928,729]", 144 px tall (wrapped) with the '+ 11' gutter at [946,1261] on its right in the mirrored RTL row; the on-screen alignment/continuation appearance is the visual reviewer's call on e1.png.
[e3] same PR in side-by-side mode (wide/tablet layout), Arabic RTL -> pass :: android emulator-5554: log 'SCENE e3 OK'; e3.txt shows resource-id="diff-mode-side-by-side" checked="true" (mode active) and the new-column prerequisite code TextView bounds="[0,1575][392,1911]" (left edge 0, wrapped tall in the narrow column); the tablet branch is unreachable on this 1080x2400 ~3x phone emulator (short-edge gate >=600dp), so it was forced by a temporary is-tablet.ts hardcode that was reverted (git status clean, UI hot-reloaded to unified); rows read 'الجديد فقط:' because the PR is pure-add (+82/-0) so the old column holds no code; alignment appearance is the visual reviewer's call on e3.png.
[e2] Arabic RTL: hunk header above line 1 reads @@ -0,0 +1,82 @@ left to right -> pass :: android emulator-5604: e2-scene.log line 1 'SCENE e2 OK'; line 22 'android.widget.TextView @@ -0,0 +1,82 @@ tappable [36,625][1044,664]' sits directly above the line-1 row (line 23) in the Arabic RTL Files diff with unified mode checked, each sign preceding its number; screenshot e2.png captured for the visual reviewer; zero UX defects.
[e4] English LTR: code still left-aligned, gutter on the left, hunk header uncha -> pass :: android emulator-5604: e4-scene.log line 1 'SCENE e4 OK'; line 22 shows the same header 'android.widget.TextView @@ -0,0 +1,82 @@ tappable [36,625][1044,664]' and line 24 shows the gutter 'android.widget.TextView + 1 tappable [80,681][133,729]' on the left with the code text at x=152 to its right (vs x=946 in the RTL run, e2-scene.log line 24); screenshot e4.png captured for the visual reviewer; zero UX defects.
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-pr-diff-expanded-the-diff-text-is-center-aligned-618e3-d46c/e2e-mobile-app/e1-digest.log
android.widget.TextView +82 tappable [773,550][821,587]
android.widget.TextView -0 tappable [728,550][754,587]
android.widget.CheckBox تحديد README.md كملف تم الاطلاع عليه tappable [37,501][119,583]
android.view.ViewGroup ترويسة المقطع @@ -0,0 +1,82 @@ tappable [0,616][1080,676]
android.widget.TextView @@ -0,0 +1,82 @@ tappable [36,625][1044,664]
android.widget.Button السطر 1، مضاف: # tax-report-generator، اضغط للتعليق tappable [0,676][1080,734]
android.widget.TextView + 1 tappable [946,681][999,729]
android.view.ViewGroup السطر 1، مضاف: # tax-report-generator tappable [0,676][928,734]
android.widget.TextView # tax-report-generator tappable [0,681][928,729]
android.widget.Button السطر 2، مضاف: (فارغ)، اضغط للتعليق tappable [0,734][1080,792]
android.widget.TextView + 2 tappable [946,739][999,787]
android.view.ViewGroup السطر 2، مضاف: (فارغ) tappable [0,734][928,792]
android.widget.Button السطر 3، مضاف: Tax report generation tool.، اضغط للتعليق tappable [0,792][1080,850]
android.widget.TextView + 3 tappable [946,797][999,845]
android.view.ViewGroup السطر 3، مضاف: Tax report generation tool. tappable [0,792][928,850]
android.widget.TextView Tax report generation tool. tappable [0,797][928,845]
android.widget.Button السطر 4، مضاف: (فارغ)، اضغط للتعليق tappable [0,850][1080,908]
android.widget.TextView + 4 tappable [946,855][999,903]
android.view.ViewGroup السطر 4، مضاف: (فارغ) tappable [0,850][928,908]
android.widget.Button السطر 5، مضاف: ## Getting Started، اضغط للتعليق tappable [0,908][1080,966]
android.widget.TextView + 5 tappable [946,913][999,961]
android.view.ViewGroup السطر 5، مضاف: ## Getting Started tappable [0,908][928,966]
android.widget.TextView ## Getting Started tappable [0,913][928,961]
android.widget.Button السطر 6، مضاف: (فارغ)، اضغط للتعليق tappable [0,966][1080,1024]
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-pr-diff-expanded-the-diff-text-is-center-aligned-618e3-d46c/e2e-mobile-app/e1.txt
<redacted>
                                          </android.widget.Button>
                                        </android.view.ViewGroup>
                                      </android.view.ViewGroup>
                                    </android.widget.ScrollView>
                                  </android.view.ViewGroup>
                                </android.view.ViewGroup>
                              </android.view.ViewGroup>
                            </android.widget.ScrollView>
                          </android.view.ViewGroup>
                        </android.view.ViewGroup>
                      </android.view.ViewGroup>
<redacted>
                    </android.view.ViewGroup>
                  </android.view.ViewGroup>
                </android.view.ViewGroup>
              </android.widget.FrameLayout>
            </android.widget.FrameLayout>
          </android.widget.FrameLayout>
        </android.widget.LinearLayout>
      </android.widget.FrameLayout>
    </android.widget.LinearLayout>
  </android.widget.FrameLayout>
</hierarchy>
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-pr-diff-expanded-the-diff-text-is-center-aligned-618e3-d46c/e2e-mobile-app/e3-digest.log
android.widget.TextView +82 tappable [773,550][821,587]
android.widget.TextView -0 tappable [728,550][754,587]
android.widget.CheckBox تحديد README.md كملف تم الاطلاع عليه tappable [37,501][119,583]
android.view.ViewGroup ترويسة المقطع @@ -0,0 +1,82 @@ tappable [0,616][1080,676]
android.widget.TextView @@ -0,0 +1,82 @@ tappable [36,625][1044,664]
android.view.ViewGroup الجديد فقط: # tax-report-generator tappable [0,676][1080,785]
android.widget.TextView 1 tappable [397,681][415,729]
android.widget.TextView # tax-report-generator tappable [0,681][392,777]
android.view.ViewGroup الجديد فقط:  tappable [0,785][1080,845]
android.widget.TextView 2 tappable [397,790][415,838]
android.view.ViewGroup الجديد فقط: Tax report generation tool. tappable [0,845][1080,954]
android.widget.TextView 3 tappable [397,850][415,898]
android.widget.TextView Tax report generation tool. tappable [0,850][392,946]
android.view.ViewGroup الجديد فقط:  tappable [0,954][1080,1014]
android.widget.TextView 4 tappable [397,959][415,1007]
android.view.ViewGroup الجديد فقط: ## Getting Started tappable [0,1014][1080,1075]
android.widget.TextView 5 tappable [397,1019][415,1067]
android.widget.TextView ## Getting Started tappable [0,1019][392,1067]
android.view.ViewGroup الجديد فقط:  tappable [0,1075][1080,1135]
android.widget.TextView 6 tappable [397,1080][415,1128]
android.view.ViewGroup الجديد فقط: ### Prerequisites tappable [0,1135][1080,1196]
android.widget.TextView 7 tappable [397,1140][415,1188]
android.widget.TextView ### Prerequisites tappable [0,1140][392,1188]
android.view.ViewGroup الجديد فقط:  tappable [0,1196][1080,1256]
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-pr-diff-expanded-the-diff-text-is-center-aligned-618e3-d46c/e2e-mobile-app/e3.txt
<redacted>
                                          </android.widget.Button>
                                        </android.view.ViewGroup>
                                      </android.view.ViewGroup>
                                    </android.widget.ScrollView>
                                  </android.view.ViewGroup>
                                </android.view.ViewGroup>
                              </android.view.ViewGroup>
                            </android.widget.ScrollView>
                          </android.view.ViewGroup>
                        </android.view.ViewGroup>
                      </android.view.ViewGroup>
<redacted>
                    </android.view.ViewGroup>
                  </android.view.ViewGroup>
                </android.view.ViewGroup>
              </android.widget.FrameLayout>
            </android.widget.FrameLayout>
          </android.widget.FrameLayout>
        </android.widget.LinearLayout>
      </android.widget.FrameLayout>
    </android.widget.LinearLayout>
  </android.widget.FrameLayout>
</hierarchy>
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-pr-diff-expanded-the-diff-text-is-center-aligned-618e3-d46c/e2e-mobile-app/e2-scene.log
android.widget.TextView +82 tappable [773,550][821,587]
android.widget.TextView -0 tappable [728,550][754,587]
android.widget.CheckBox تحديد README.md كملف تم الاطلاع عليه tappable [37,501][119,583]
android.view.ViewGroup ترويسة المقطع @@ -0,0 +1,82 @@ tappable [0,616][1080,676]
android.widget.TextView @@ -0,0 +1,82 @@ tappable [36,625][1044,664]
android.widget.Button السطر 1، مضاف: # tax-report-generator، اضغط للتعليق tappable [0,676][1080,734]
android.widget.TextView + 1 tappable [946,681][999,729]
android.view.ViewGroup السطر 1، مضاف: # tax-report-generator tappable [0,676][928,734]
android.widget.TextView # tax-report-generator tappable [0,681][928,729]
android.widget.Button السطر 2، مضاف: (فارغ)، اضغط للتعليق tappable [0,734][1080,792]
android.widget.TextView + 2 tappable [946,739][999,787]
android.view.ViewGroup السطر 2، مضاف: (فارغ) tappable [0,734][928,792]
android.widget.Button السطر 3، مضاف: Tax report generation tool.، اضغط للتعليق tappable [0,792][1080,850]
android.widget.TextView + 3 tappable [946,797][999,845]
android.view.ViewGroup السطر 3، مضاف: Tax report generation tool. tappable [0,792][928,850]
android.widget.TextView Tax report generation tool. tappable [0,797][928,845]
android.widget.Button السطر 4، مضاف: (فارغ)، اضغط للتعليق tappable [0,850][1080,908]
android.widget.TextView + 4 tappable [946,855][999,903]
android.view.ViewGroup السطر 4، مضاف: (فارغ) tappable [0,850][928,908]
android.widget.Button السطر 5، مضاف: ## Getting Started، اضغط للتعليق tappable [0,908][1080,966]
android.widget.TextView + 5 tappable [946,913][999,961]
android.view.ViewGroup السطر 5، مضاف: ## Getting Started tappable [0,908][928,966]
android.widget.TextView ## Getting Started tappable [0,913][928,961]
android.widget.Button السطر 6، مضاف: (فارغ)، اضغط للتعليق tappable [0,966][1080,1024]
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-pr-diff-expanded-the-diff-text-is-center-aligned-618e3-d46c/e2e-mobile-app/e4-scene.log
android.widget.TextView +82 tappable [274,550][322,587]
android.widget.TextView -0 tappable [340,550][366,587]
android.widget.CheckBox Mark README.md as viewed tappable [961,501][1043,583]
android.view.ViewGroup Hunk header @@ -0,0 +1,82 @@ tappable [0,616][1080,676]
android.widget.TextView @@ -0,0 +1,82 @@ tappable [36,625][1044,664]
android.widget.Button Added line 1: # tax-report-generator, tap to comment tappable [0,676][1080,734]
android.widget.TextView + 1 tappable [80,681][133,729]
android.view.ViewGroup Added line 1: # tax-report-generator tappable [152,676][1080,734]
android.widget.TextView # tax-report-generator tappable [152,681][1080,729]
android.widget.Button Added line 2: (empty), tap to comment tappable [0,734][1080,792]
android.widget.TextView + 2 tappable [80,739][133,787]
android.view.ViewGroup Added line 2: (empty) tappable [152,734][1080,792]
android.widget.Button Added line 3: Tax report generation tool., tap to comment tappable [0,792][1080,850]
android.widget.TextView + 3 tappable [80,797][133,845]
android.view.ViewGroup Added line 3: Tax report generation tool. tappable [152,792][1080,850]
android.widget.TextView Tax report generation tool. tappable [152,797][1080,845]
android.widget.Button Added line 4: (empty), tap to comment tappable [0,850][1080,908]
android.widget.TextView + 4 tappable [80,855][133,903]
android.view.ViewGroup Added line 4: (empty) tappable [152,850][1080,908]
android.widget.Button Added line 5: ## Getting Started, tap to comment tappable [0,908][1080,966]
android.widget.TextView + 5 tappable [80,913][133,961]
android.view.ViewGroup Added line 5: ## Getting Started tappable [152,908][1080,966]
android.widget.TextView ## Getting Started tappable [152,913][1080,961]
Owner request

Explorer finding: pr-diff-expanded: The diff text is center-aligned, so the wrapped prerequisite line's continuation "running against --ibkr)" floats mid-width instead of aligning with the line-number column its first line uses.

The user-agent explorer found this while using the app like a user.
One finding per item; the explorer never edits product code.

Flow: pr-diff-expanded
Found on revision: 5327758

Repro:

  1. set this state first: the device in light mode
  2. open the app on emulator-5554
  3. reach pr-diff-expanded
  4. the capture shows the defect named below

Observed: The diff text is center-aligned, so the wrapped prerequisite line's continuation "running against --ibkr)" floats mid-width instead of aligning with the line-number column its first line uses.
Expected: the screen renders without this defect

Evidence (from the device run):

Follow-ups (not changed here)

  • not proved live: Same Arabic RTL screen: the hunk header above line 1 reads @@ -0,0 +1,82 @@ left to right (each sign stays with its number, - first); before the fix the device drew @@ 1,82+ 0,0- @@. (no capture cited it)
  • not proved live: Same PR in side-by-side mode (wide/tablet layout, Arabic RTL): both the old and the new column's code is left-aligned and a wrapped line's continuation starts under its first line. (no capture cited it)
  • not proved live: Switch the app to English (LTR) and reopen the same diff: code still left-aligned with the gutter on the left and the hunk header unchanged — no regression in an LTR interface. (no capture cited it)

Open findings (not fixed here)

  • not proved live: pr-diff-expanded.png is no longer on the host that took it, so no publish can carry it

@kilo-code-bot

kilo-code-bot Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

Incremental review since b7951eac: the PR's eight mobile diff-direction files have identical content at HEAD (36dac6e8e), so the previously verified LTR_TEXT_DIRECTION scoping (applied to the code Text, not a wrapping View, and spread into new style objects) still holds and no new changed-line defects were found.

Files Reviewed (8 files)
  • apps/mobile/src/lib/rtl-text.ts
  • apps/mobile/src/components/pr-review/diff/diff-line.tsx
  • apps/mobile/src/components/pr-review/diff/diff-line.mounted.test.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-hunk-rows.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-hunk-rows.test.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-hunk-rows.mounted.test.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-side-by-side-row.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-side-by-side-row.mounted.test.tsx
Previous Review Summary (commit b7951ea)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit b7951ea)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Reviewed the mobile RTL diff-direction fix (8 files): LTR_TEXT_DIRECTION is correctly applied to unified code, both side-by-side columns, and both hunk headers, and the shared Text style ordering makes the caller's LTR direction win over the inherited RTL writingDirection.

Files Reviewed (8 files)
  • apps/mobile/src/lib/rtl-text.ts
  • apps/mobile/src/components/pr-review/diff/diff-line.tsx
  • apps/mobile/src/components/pr-review/diff/diff-line.mounted.test.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-hunk-rows.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-hunk-rows.test.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-hunk-rows.mounted.test.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-side-by-side-row.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-side-by-side-row.mounted.test.tsx

No changed-line defects found. The direction is scoped to the code Text (not a wrapping View), so the gutter is not mirrored, and { ...LTR_TEXT_DIRECTION } is spread into new style objects rather than mutating the shared constant, so there is no shared-state or memory-leak concern.


Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0

Review guidance: REVIEW.md from base branch main

@iscekic
iscekic marked this pull request as draft September 19, 2026 22:21
@iscekic
iscekic force-pushed the kwf/explorer-pr-diff-expanded-the-diff-text-is-center-aligned-618e3-d46c branch from ecb2119 to 36dac6e Compare September 19, 2026 23:45
@iscekic
iscekic marked this pull request as ready for review September 19, 2026 23:54
@iscekic

iscekic commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator Author

This description names a scenario the proof did not capture:

  • not proved live: Same Arabic RTL screen: the hunk header above line 1 reads @@ -0,0 +1,82 @@ left to right (each sign stays with its number, - first); before the fix the device drew @@ 1,82+ 0,0- @@. (no capture cited it)

A repeated proof run rebuilds the same evidence, so no proof run is dispatched for a named gap. Merging with this gap open is your decision.

@iscekic iscekic added the human-ready The PR is ready for human review. label Sep 20, 2026
@iscekic iscekic self-assigned this Sep 20, 2026

@eshurakov eshurakov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved after a shallow triage pass. No blocking findings.

@iscekic
iscekic merged commit 342d6c1 into main Sep 21, 2026
29 checks passed
@iscekic
iscekic deleted the kwf/explorer-pr-diff-expanded-the-diff-text-is-center-aligned-618e3-d46c branch September 21, 2026 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

human-ready The PR is ready for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants