Commit 13944da
authored
feat: introduce rudimentary RTL support to the RN SDK (#3522)
## 🎯 Goal
This PR addresses a bunch of RTL issues our SDK has had over the last
couple of majors and makes sure we have first class support for it.
## Summary
This PR fixes a set of RTL specific UI regressions that were affecting
several surfaces in the SDK.
The issues were not all caused by the same thing. Some were caused by
relying on implicit platform mirroring, some by scroll/list containers
using the wrong coordinate space in RTL, and some by spacing being
applied on the wrong level of a scrollable surface. The result was a mix
of broken alignment, unstable animations, blank gallery content, and
inconsistent behavior between iOS and Android.
This PR makes those behaviors explicit and stabilizes the affected
components without changing their public API.
## Problems fixed
- Attachment upload preview strip behaved incorrectly in RTL, especially
on Android.
- Poll creation and poll result modals had broken spacing in RTL, with
content appearing pinned to one side.
- Poll text alignment was inconsistent between Android and iOS.
- Poll inputs inside poll screens/modals were not following the same RTL
text alignment behavior as the main composer input.
- The image gallery could open in RTL, but images would not render even
though gestures still worked.
- The thread list item channel name at the top of each thread card was
aligned incorrectly in RTL.
## What changed
### RTL attachment preview stability
The attachment preview strip now uses a stable coordinate-space approach
in RTL so it no longer fights the list/pager/layout system.
- stabilized the horizontal preview list so RTL no longer depends on
fragile scroll compensation behavior
- removed the RTL specific scroll race that was causing inconsistent
Android behavior
- kept the visual RTL ordering/alignment behavior while avoiding the
previous listwide bounce/shift issues
- disabled problematic overscroll behavior where needed so native scroll
physics stop interfering with the preview strip
Unfortunately, I could not at all get RTL to work natively here due to
the fact that `reanimated`'s layout animations were completely messing
with the underlying `ScrollView`'s width calculations when horizontal.
After a couple of hours of debugging I settled with disabling RTL
directly and handling all edge cases manually.
This was the area with the most platform sensitivity, especially on
Android.
### Poll modal spacing and layout fixes
The poll modal issue turned out not to be an individual-screen bug. The
main problem was that outer padding was being applied on scroll/list
wrappers, which behaves badly in Android RTL and can look like
horizontal padding is only applied from one side.
The fix was to move spacing from outer scroll containers into their
content containers for the shared poll modal surfaces.
This fixes layout issues in:
- create poll
- poll results
- poll answers list
- full option results views
- other shared poll modal surfaces using the same pattern
As part of that cleanup, earlier safe-area wrapper changes were reverted
because they were not the actual fix.
### Poll text alignment on iOS RTL
Poll titles, labels, cards, and result text were relying too much on
implicit platform behavior. Android happened to look mostly correct,
while iOS did not.
This PR makes the relevant non-input poll text alignment explicit where
needed so the iOS rendering matches the intended RTL layout.
It also replaces a few LTR-only spacing rules with logical start-aware
spacing where the text/result rows needed it.
### Poll input alignment consistency
Poll inputs now follow the same RTL alignment rule as the existing
autocomplete composer input instead of using a separate behavior.
That means poll inputs now use:
- textAlign: I18nManager.isRTL ? 'right' : 'left'
This was applied to the poll-specific input surfaces, including modal
inputs, so editable text behaves consistently across the SDK.
### Image gallery rendering in RTL
The gallery rendering issue was caused by a coordinate-space mismatch.
The pager/slide math in the image gallery is LTR-based, but the gallery
container was still inheriting RTL layout direction. In practice, that
meant the gallery could open and still respond to swipe/
close gestures, while the image slides themselves were effectively laid
out off-screen.
The fix was to force only the gallery pager strip into LTR coordinates
while leaving the rest of the experience intact.
This restores image rendering in RTL without changing the gallery
gesture model.
### Thread list item alignment
The channel name at the top of thread list items now uses explicit
alignment so it renders correctly in RTL.
This is a narrow change scoped only to that text style.
## Why this approach
The common theme across these issues is that implicit RTL handling was
not reliable enough for these components.
The fixes in this PR intentionally avoid broad “flip everything” logic.
Instead, each surface now expresses the behavior it actually needs:
- content containers own spacing in scrollable modal surfaces
- text components that need explicit alignment get explicit alignment
- input components use the same RTL rule as the main composer
- animation/pager surfaces that depend on physical coordinates are
pinned to an LTR coordinate space when that is what their math assumes
That keeps the fixes targeted and avoids introducing new regressions in
already. correct layouts.
I'm sure there are other edge cases with RTL that I did not manage to
notice, however as a first step this should do just fine, especially
considering we've never had any RTL support before.
## 🛠 Implementation details
<!-- Provide a description of the implementation -->
## 🎨 UI Changes
<!-- Add relevant screenshots -->
<details>
<summary>iOS</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
<details>
<summary>Android</summary>
<table>
<thead>
<tr>
<td>Before</td>
<td>After</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<!--<img src="" /> -->
</td>
<td>
<!--<img src="" /> -->
</td>
</tr>
</tbody>
</table>
</details>
## 🧪 Testing
<!-- Explain how this change can be tested (or why it can't be tested)
-->
## ☑️ Checklist
- [ ] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [ ] PR targets the `develop` branch
- [ ] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
- [ ] SampleApp iOS and Android
- [ ] Expo iOS and Android1 parent 9bbd89c commit 13944da
31 files changed
Lines changed: 761 additions & 286 deletions
File tree
- examples/SampleApp
- src
- components
- context
- package/src
- components
- AttachmentPicker
- ImageGallery
- __tests__
- MessageInput/components/AttachmentPreview
- Message
- MessageItemView
- Poll
- components
- PollResults
- ProgressControl
- Reply
- ThreadList
- UIComponents
- __tests__
- ui/Input
- contexts/overlayContext
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| |||
99 | 99 | | |
100 | 100 | | |
101 | 101 | | |
| 102 | + | |
102 | 103 | | |
103 | 104 | | |
104 | 105 | | |
| |||
131 | 132 | | |
132 | 133 | | |
133 | 134 | | |
| 135 | + | |
134 | 136 | | |
135 | 137 | | |
136 | 138 | | |
| |||
150 | 152 | | |
151 | 153 | | |
152 | 154 | | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
153 | 164 | | |
154 | 165 | | |
155 | 166 | | |
| |||
188 | 199 | | |
189 | 200 | | |
190 | 201 | | |
191 | | - | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
192 | 217 | | |
193 | 218 | | |
194 | 219 | | |
| |||
223 | 248 | | |
224 | 249 | | |
225 | 250 | | |
226 | | - | |
| 251 | + | |
227 | 252 | | |
228 | 253 | | |
229 | 254 | | |
| |||
258 | 283 | | |
259 | 284 | | |
260 | 285 | | |
261 | | - | |
| 286 | + | |
262 | 287 | | |
263 | 288 | | |
264 | 289 | | |
| |||
294 | 319 | | |
295 | 320 | | |
296 | 321 | | |
| 322 | + | |
| 323 | + | |
297 | 324 | | |
298 | 325 | | |
299 | 326 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
3 | 12 | | |
4 | 13 | | |
5 | 14 | | |
| |||
31 | 40 | | |
32 | 41 | | |
33 | 42 | | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
34 | 48 | | |
35 | 49 | | |
36 | 50 | | |
37 | | - | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
38 | 71 | | |
39 | 72 | | |
40 | 73 | | |
41 | 74 | | |
42 | | - | |
| 75 | + | |
43 | 76 | | |
44 | 77 | | |
45 | 78 | | |
| |||
51 | 84 | | |
52 | 85 | | |
53 | 86 | | |
| 87 | + | |
54 | 88 | | |
55 | 89 | | |
56 | 90 | | |
| |||
65 | 99 | | |
66 | 100 | | |
67 | 101 | | |
68 | | - | |
| 102 | + | |
69 | 103 | | |
70 | 104 | | |
71 | 105 | | |
| |||
74 | 108 | | |
75 | 109 | | |
76 | 110 | | |
77 | | - | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
78 | 115 | | |
79 | 116 | | |
80 | 117 | | |
| |||
84 | 121 | | |
85 | 122 | | |
86 | 123 | | |
| 124 | + | |
87 | 125 | | |
88 | 126 | | |
89 | 127 | | |
| |||
105 | 143 | | |
106 | 144 | | |
107 | 145 | | |
108 | | - | |
| 146 | + | |
109 | 147 | | |
110 | 148 | | |
111 | 149 | | |
112 | 150 | | |
113 | 151 | | |
| 152 | + | |
114 | 153 | | |
115 | 154 | | |
116 | 155 | | |
| |||
125 | 164 | | |
126 | 165 | | |
127 | 166 | | |
128 | | - | |
| 167 | + | |
129 | 168 | | |
130 | 169 | | |
131 | 170 | | |
132 | 171 | | |
133 | 172 | | |
| 173 | + | |
134 | 174 | | |
135 | 175 | | |
136 | 176 | | |
| |||
139 | 179 | | |
140 | 180 | | |
141 | 181 | | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
142 | 231 | | |
143 | 232 | | |
144 | 233 | | |
145 | 234 | | |
146 | 235 | | |
147 | | - | |
| 236 | + | |
148 | 237 | | |
149 | 238 | | |
150 | 239 | | |
151 | 240 | | |
152 | 241 | | |
| 242 | + | |
153 | 243 | | |
154 | 244 | | |
155 | 245 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
| 19 | + | |
18 | 20 | | |
19 | 21 | | |
20 | 22 | | |
| |||
Lines changed: 14 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
| |||
38 | 39 | | |
39 | 40 | | |
40 | 41 | | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
41 | 45 | | |
42 | 46 | | |
43 | 47 | | |
| |||
105 | 109 | | |
106 | 110 | | |
107 | 111 | | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
108 | 121 | | |
109 | 122 | | |
110 | 123 | | |
| 124 | + | |
111 | 125 | | |
112 | 126 | | |
113 | 127 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
284 | 284 | | |
285 | 285 | | |
286 | 286 | | |
287 | | - | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
288 | 291 | | |
289 | 292 | | |
290 | 293 | | |
| |||
399 | 402 | | |
400 | 403 | | |
401 | 404 | | |
| 405 | + | |
402 | 406 | | |
403 | 407 | | |
404 | 408 | | |
| |||
Lines changed: 33 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
79 | 80 | | |
80 | 81 | | |
81 | 82 | | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
82 | 96 | | |
83 | 97 | | |
84 | 98 | | |
| |||
99 | 113 | | |
100 | 114 | | |
101 | 115 | | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
102 | 135 | | |
0 commit comments