fix: RTL URL parameter rtl=false now correctly disables RTL mode#7464
Conversation
The rtl parameter callback only handled rtl=true (checkVal was 'true'), so rtl=false was ignored and the layout stayed in RTL from the cookie. Now accepts any value and sets rtlIsTrue = (val === 'true'). Also always applies the RTL setting instead of only when true, so switching from rtl=true to rtl=false takes effect. Fixes ether#5559 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
/review |
Code Review by Qodo
1. rtl fix lacks test
|
Review Summary by QodoFix RTL URL parameter rtl=false disabling RTL mode correctly
WalkthroughsDescription• Fix RTL URL parameter rtl=false being ignored after RTL enabled • Changed callback to accept any value, not just 'true' • Explicitly set rtlIsTrue based on parameter value equality • Always apply RTL setting to view, not conditionally Diagramflowchart LR
A["rtl URL parameter"] -->|checkVal null| B["Callback fires for any value"]
B -->|val === 'true'| C["rtlIsTrue set correctly"]
C -->|Always call| D["changeViewOption applied"]
D -->|Result| E["RTL mode toggles properly"]
File Changes1. src/static/js/pad.ts
|
Code Review by Qodo
1. rtl fix lacks test
|
| name: 'rtl', | ||
| checkVal: 'true', | ||
| checkVal: null, | ||
| callback: (val) => { | ||
| settings.rtlIsTrue = true; | ||
| settings.rtlIsTrue = val === 'true'; | ||
| }, |
There was a problem hiding this comment.
1. rtl fix lacks test 📘 Rule violation ☼ Reliability
This PR fixes a user-facing regression in the rtl URL parameter handling but does not include an automated regression test to prevent reintroduction. Without a test that covers ?rtl=true then ?rtl=false, the bug can easily return unnoticed.
Agent Prompt
## Issue description
A bug fix was made to ensure `?rtl=false` disables RTL mode, but there is no automated regression test to ensure the behavior remains correct.
## Issue Context
The fixed behavior is: after enabling RTL (via URL/cookie), loading with `?rtl=false` must switch back to LTR (and not remain stuck in RTL).
## Fix Focus Areas
- src/tests/frontend-new/specs/language.spec.ts[51-87]
- src/tests/frontend-new/helper/padHelper.ts[107-130]
- src/static/js/pad.ts[121-126]
- src/static/js/pad.ts[548-559]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The unconditional changeViewOption('rtlIsTrue', false) overwrote
cookie-persisted RTL preferences and language-direction defaults.
Track explicit setting with rtlIsExplicit flag so we only override
when the user or server actually specified an rtl value.
Adds regression tests for rtl=true, rtl=false, and cookie persistence.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The RTL changeViewOption call was racing with padeditor.init() — the async setViewOptions(initialViewOptions) at the end of init overwrote the URL-param-based RTL setting. Moving it into postAceInit ensures padeditor is fully initialized. Also switched tests to use Playwright auto-retrying assertions for robustness. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three issues fixed:
- setCheckbox used .attr('checked') instead of .prop('checked'), so the
JS checked property was never set and Playwright saw unchecked state
- html10n localized event overwrote RTL setting from URL params and
cookie preferences; now skips override when either is active
- Server default padOptions.rtl:false was treated as explicit, overwriting
cookie-persisted RTL; added fromUrl flag to distinguish URL from server
All 94 Playwright tests and 740 backend tests pass locally.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
`?showLineNumbers=false` and `?useMonospaceFont=true` were being silently clobbered shortly after pad load. Same race that affected `?rtl=false` before #7464: 1. _afterHandshake → getParams() sets settings.LineNumbersDisabled (or useMonospaceFontGlobal, noColors). 2. _afterHandshake calls padeditor.init(view).then(postAceInit) — async; ace iframes still loading. 3. Sync tail of _afterHandshake hits the URL-param overrides and calls changeViewOption('showLineNumbers', false) etc. These queue setProperty('showslinenumbers', false) in Ace2Editor's actionsPendingInit queue (loaded=false). 4. ace.init resolves → loaded=true → queue flushes → URL-driven value applied. 5. padeditor.init resumes past its own await and calls setViewOptions(initialViewOptions) — initialViewOptions is built from clientVars.initialOptions.view (server defaults ∨ cookie), which does NOT carry the URL preference. The resulting setProperty('showslinenumbers', true) runs against loaded=true ace and immediately re-shows the gutter. #7464 noticed this race for RTL and moved the override into postAceInit. The neighbouring blocks for showLineNumbers / noColors / useMonospaceFontGlobal were left at the synchronous-tail site — generalise the same fix to all three. Direct-browser users typically had a `prefs` cookie with showLineNumbers=false from a prior in-pad toggle, so the initialViewOptions value happened to match the URL param and the race was unobservable. Cross-context iframe embeds (the reporter's configuration) start with no cookie, so the server default true fights the URL false and the race becomes visible. Adds src/tests/frontend-new/specs/url_view_options.spec.ts covering the showLineNumbers=false / =true / useMonospaceFont=true cases on initial-load navigation (the path where the race actually fires). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…7843) * fix(pad): URL view-option params lost to padeditor.init race (#7840) `?showLineNumbers=false` and `?useMonospaceFont=true` were being silently clobbered shortly after pad load. Same race that affected `?rtl=false` before #7464: 1. _afterHandshake → getParams() sets settings.LineNumbersDisabled (or useMonospaceFontGlobal, noColors). 2. _afterHandshake calls padeditor.init(view).then(postAceInit) — async; ace iframes still loading. 3. Sync tail of _afterHandshake hits the URL-param overrides and calls changeViewOption('showLineNumbers', false) etc. These queue setProperty('showslinenumbers', false) in Ace2Editor's actionsPendingInit queue (loaded=false). 4. ace.init resolves → loaded=true → queue flushes → URL-driven value applied. 5. padeditor.init resumes past its own await and calls setViewOptions(initialViewOptions) — initialViewOptions is built from clientVars.initialOptions.view (server defaults ∨ cookie), which does NOT carry the URL preference. The resulting setProperty('showslinenumbers', true) runs against loaded=true ace and immediately re-shows the gutter. #7464 noticed this race for RTL and moved the override into postAceInit. The neighbouring blocks for showLineNumbers / noColors / useMonospaceFontGlobal were left at the synchronous-tail site — generalise the same fix to all three. Direct-browser users typically had a `prefs` cookie with showLineNumbers=false from a prior in-pad toggle, so the initialViewOptions value happened to match the URL param and the race was unobservable. Cross-context iframe embeds (the reporter's configuration) start with no cookie, so the server default true fights the URL false and the race becomes visible. Adds src/tests/frontend-new/specs/url_view_options.spec.ts covering the showLineNumbers=false / =true / useMonospaceFont=true cases on initial-load navigation (the path where the race actually fires). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(types): annotate navigateWithParam helper params Fixes CI ts-check: parameters page/padId/param implicitly had `any`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
The
?rtl=falseURL parameter was ignored — once RTL was enabled (via?rtl=trueor cookie), it couldn't be disabled via URL.Root Cause
The
rtlparameter ingetParametershadcheckVal: 'true', meaning the callback only fired when the value was exactly'true'. Whenrtl=falsewas passed, the callback didn't run and the setting stayed at whatever the cookie had.Also,
changeViewOption('rtlIsTrue', ...)was only called whentrue, never whenfalse, so even if the setting was correctly set tofalse, the view wasn't updated.Fix
checkValtonullso the callback fires for any valuertlIsTrue = (val === 'true')— explicitlyfalsefor non-true valueschangeViewOptionis always called with the current setting, not conditionallyTest plan
Fixes #5559
🤖 Generated with Claude Code