Skip to content

Commit 1b688a9

Browse files
Merge branch 'RocketChat:develop' into develop
2 parents 0af38de + 566e100 commit 1b688a9

File tree

12 files changed

+7644
-3884
lines changed

12 files changed

+7644
-3884
lines changed

android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import chat.rocket.reactnative.storage.MMKVKeyManager;
2020
import chat.rocket.reactnative.storage.SecureStoragePackage;
2121
import chat.rocket.reactnative.notification.VideoConfTurboPackage
2222
import chat.rocket.reactnative.notification.PushNotificationTurboPackage
23+
import chat.rocket.reactnative.scroll.InvertedScrollPackage
2324

2425
/**
2526
* Main Application class.
@@ -44,6 +45,7 @@ open class MainApplication : Application(), ReactApplication {
4445
add(VideoConfTurboPackage())
4546
add(PushNotificationTurboPackage())
4647
add(SecureStoragePackage())
48+
add(InvertedScrollPackage())
4749
}
4850

4951
override fun getJSMainModuleName(): String = "index"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package chat.rocket.reactnative.scroll;
2+
3+
import android.view.View;
4+
import com.facebook.react.views.view.ReactViewGroup;
5+
import java.util.ArrayList;
6+
import java.util.Collections;
7+
8+
/**
9+
* Content view for inverted FlatLists. Reports its children to accessibility in reversed order so
10+
* TalkBack traversal matches the visual order (newest-first) when used inside InvertedScrollView.
11+
*/
12+
public class InvertedScrollContentView extends ReactViewGroup {
13+
14+
public InvertedScrollContentView(android.content.Context context) {
15+
super(context);
16+
}
17+
18+
@Override
19+
public void addChildrenForAccessibility(ArrayList<View> outChildren) {
20+
super.addChildrenForAccessibility(outChildren);
21+
Collections.reverse(outChildren);
22+
}
23+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package chat.rocket.reactnative.scroll;
2+
3+
import com.facebook.react.module.annotations.ReactModule;
4+
import com.facebook.react.uimanager.ThemedReactContext;
5+
import com.facebook.react.views.view.ReactViewManager;
6+
7+
/**
8+
* View manager for InvertedScrollContentView. Behaves like a View but reports children in reversed
9+
* order for accessibility so TalkBack matches the visual order in inverted lists.
10+
*/
11+
@ReactModule(name = InvertedScrollContentViewManager.REACT_CLASS)
12+
public class InvertedScrollContentViewManager extends ReactViewManager {
13+
14+
public static final String REACT_CLASS = "InvertedScrollContentView";
15+
16+
@Override
17+
public String getName() {
18+
return REACT_CLASS;
19+
}
20+
21+
@Override
22+
public InvertedScrollContentView createViewInstance(ThemedReactContext context) {
23+
return new InvertedScrollContentView(context);
24+
}
25+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package chat.rocket.reactnative.scroll;
2+
3+
import com.facebook.react.ReactPackage;
4+
import com.facebook.react.bridge.NativeModule;
5+
import com.facebook.react.bridge.ReactApplicationContext;
6+
import com.facebook.react.uimanager.ViewManager;
7+
import java.util.Collections;
8+
import java.util.List;
9+
10+
public class InvertedScrollPackage implements ReactPackage {
11+
12+
@Override
13+
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
14+
return Collections.emptyList();
15+
}
16+
17+
@Override
18+
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
19+
List<ViewManager> managers = new java.util.ArrayList<>();
20+
managers.add(new InvertedScrollViewManager());
21+
managers.add(new InvertedScrollContentViewManager());
22+
return managers;
23+
}
24+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package chat.rocket.reactnative.scroll;
2+
3+
import android.view.View;
4+
import com.facebook.react.bridge.ReactContext;
5+
import com.facebook.react.views.scroll.ReactScrollView;
6+
import java.util.ArrayList;
7+
import java.util.Collections;
8+
9+
// When a FlatList is inverted (inverted={true}), React Native uses scaleY: -1 transform which
10+
// visually inverts the list but Android still reports children in array order. This view overrides
11+
// addChildrenForAccessibility to reverse the order so TalkBack matches the visual order.
12+
13+
public class InvertedScrollView extends ReactScrollView {
14+
15+
private boolean mIsInvertedVirtualizedList = false;
16+
17+
public InvertedScrollView(ReactContext context) {
18+
super(context);
19+
}
20+
21+
22+
// Set whether this ScrollView is used for an inverted virtualized list. When true, we reverse the
23+
// accessibility traversal order to match the visual order.
24+
25+
public void setIsInvertedVirtualizedList(boolean isInverted) {
26+
mIsInvertedVirtualizedList = isInverted;
27+
}
28+
29+
@Override
30+
public void addChildrenForAccessibility(ArrayList<View> outChildren) {
31+
super.addChildrenForAccessibility(outChildren);
32+
if (mIsInvertedVirtualizedList) {
33+
Collections.reverse(outChildren);
34+
}
35+
}
36+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package chat.rocket.reactnative.scroll;
2+
3+
import com.facebook.react.module.annotations.ReactModule;
4+
import com.facebook.react.uimanager.ThemedReactContext;
5+
import com.facebook.react.views.scroll.ReactScrollViewManager;
6+
7+
/**
8+
* View manager for {@link InvertedScrollView}. Registers as "InvertedScrollView" to avoid
9+
* collision with core RCTScrollView. Inherits all ScrollView props from ReactScrollViewManager;
10+
* FlatList passes isInvertedVirtualizedList when inverted, which is applied by the parent setter.
11+
*/
12+
@ReactModule(name = InvertedScrollViewManager.REACT_CLASS)
13+
public class InvertedScrollViewManager extends ReactScrollViewManager {
14+
15+
public static final String REACT_CLASS = "InvertedScrollView";
16+
17+
@Override
18+
public String getName() {
19+
return REACT_CLASS;
20+
}
21+
22+
@Override
23+
public InvertedScrollView createViewInstance(ThemedReactContext context) {
24+
return new InvertedScrollView(context);
25+
}
26+
}

app/containers/message/Message.stories.tsx

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ export const WithImage = () => (
673673
attachments={[
674674
{
675675
title: 'This is a title',
676-
description: 'This is a description',
676+
description: 'This is a description :nyan_rocket:',
677677
image_url: '/dummypath'
678678
}
679679
]}
@@ -697,6 +697,19 @@ export const WithImage = () => (
697697
}
698698
]}
699699
/>
700+
<Message
701+
msg='multi file'
702+
attachments={[
703+
{
704+
title: 'This is a title',
705+
image_url: '/dummypath'
706+
},
707+
{
708+
title: 'This is a title',
709+
image_url: '/dummypath'
710+
}
711+
]}
712+
/>
700713
<Message
701714
attachments={[
702715
{
@@ -724,7 +737,21 @@ export const WithImageLargeFont = () => (
724737
attachments={[
725738
{
726739
title: 'This is a title',
727-
description: 'This is a description :nyan_rocket:',
740+
description: 'Header false',
741+
image_url: '/dummypath'
742+
}
743+
]}
744+
isHeader={false}
745+
/>
746+
<Message
747+
msg='multi file'
748+
attachments={[
749+
{
750+
title: 'This is a title',
751+
image_url: '/dummypath'
752+
},
753+
{
754+
title: 'This is a title',
728755
image_url: '/dummypath'
729756
}
730757
]}
@@ -756,16 +783,22 @@ export const WithVideo = () => (
756783
attachments={[
757784
{
758785
title: 'This is a title',
786+
description: 'Header false',
759787
video_url: '/dummypath'
760-
},
788+
}
789+
]}
790+
isHeader={false}
791+
/>
792+
<Message
793+
msg='multi file'
794+
attachments={[
761795
{
762796
title: 'This is a title',
763-
description: 'This is a description :nyan_rocket:',
764797
video_url: '/dummypath'
765798
},
766799
{
767800
title: 'This is a title',
768-
video_url: '/dummypath2'
801+
video_url: '/dummypath'
769802
}
770803
]}
771804
/>
@@ -791,6 +824,19 @@ export const WithVideoLargeFont = () => (
791824
}
792825
]}
793826
/>
827+
<MessageLargeFont
828+
msg='multi file'
829+
attachments={[
830+
{
831+
title: 'This is a title',
832+
video_url: '/dummypath'
833+
},
834+
{
835+
title: 'This is a title',
836+
video_url: '/dummypath'
837+
}
838+
]}
839+
/>
794840
</>
795841
);
796842

@@ -805,19 +851,23 @@ export const WithAudio = () => (
805851
}
806852
]}
807853
/>
808-
<Message msg='First message' isHeader={false} />
809854
<Message
810855
attachments={[
811856
{
812857
title: 'This is a title',
813-
description: 'This is a description',
858+
description: 'Header false',
814859
audio_url: '/dummypath'
815860
}
816861
]}
817862
isHeader={false}
818863
/>
819864
<Message
865+
msg='multi file'
820866
attachments={[
867+
{
868+
title: 'This is a title',
869+
audio_url: '/dummypath'
870+
},
821871
{
822872
title: 'This is a title',
823873
audio_url: '/dummypath'
@@ -878,7 +928,17 @@ export const WithAudioLargeFont = () => (
878928
isHeader={false}
879929
/>
880930
<MessageLargeFont
931+
msg='multi file'
881932
attachments={[
933+
{
934+
title: 'This is a title',
935+
audio_url: '/dummypath'
936+
},
937+
{
938+
title: 'This is a title',
939+
description: 'This is a description :nyan_rocket:',
940+
audio_url: '/dummypath'
941+
},
882942
{
883943
title: 'This is a title',
884944
audio_url: '/dummypath'
@@ -1056,6 +1116,17 @@ export const FileAttachmentsWithFilenamesLargeFont = () => (
10561116
]}
10571117
isHeader={false}
10581118
/>
1119+
<MessageLargeFont
1120+
msg='multi file'
1121+
attachments={[
1122+
{
1123+
text: 'File.pdf'
1124+
},
1125+
{
1126+
text: 'File.pdf'
1127+
}
1128+
]}
1129+
/>
10591130
</>
10601131
);
10611132

0 commit comments

Comments
 (0)