stream-chat-react-native-core 9.4.0-beta.12 → 9.4.0-beta.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/lib/commonjs/components/ImageGallery/ImageGallery.js +21 -76
  2. package/lib/commonjs/components/ImageGallery/ImageGallery.js.map +1 -1
  3. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryImage.js +6 -10
  4. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryImage.js.map +1 -1
  5. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryVideo.js +16 -14
  6. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryVideo.js.map +1 -1
  7. package/lib/commonjs/components/ImageGallery/components/ImageGalleryA11yProbe.js +67 -0
  8. package/lib/commonjs/components/ImageGallery/components/ImageGalleryA11yProbe.js.map +1 -0
  9. package/lib/commonjs/components/ImageGallery/hooks/useAnimatedGalleryStyle.js +4 -3
  10. package/lib/commonjs/components/ImageGallery/hooks/useAnimatedGalleryStyle.js.map +1 -1
  11. package/lib/commonjs/components/ImageGallery/hooks/useCurrentImageHeight.js +53 -0
  12. package/lib/commonjs/components/ImageGallery/hooks/useCurrentImageHeight.js.map +1 -0
  13. package/lib/commonjs/components/ImageGallery/hooks/useImageGalleryGestures.js +25 -31
  14. package/lib/commonjs/components/ImageGallery/hooks/useImageGalleryGestures.js.map +1 -1
  15. package/lib/commonjs/state-store/image-gallery-state-store.js +12 -3
  16. package/lib/commonjs/state-store/image-gallery-state-store.js.map +1 -1
  17. package/lib/commonjs/version.json +1 -1
  18. package/lib/module/components/ImageGallery/ImageGallery.js +21 -76
  19. package/lib/module/components/ImageGallery/ImageGallery.js.map +1 -1
  20. package/lib/module/components/ImageGallery/components/AnimatedGalleryImage.js +6 -10
  21. package/lib/module/components/ImageGallery/components/AnimatedGalleryImage.js.map +1 -1
  22. package/lib/module/components/ImageGallery/components/AnimatedGalleryVideo.js +16 -14
  23. package/lib/module/components/ImageGallery/components/AnimatedGalleryVideo.js.map +1 -1
  24. package/lib/module/components/ImageGallery/components/ImageGalleryA11yProbe.js +67 -0
  25. package/lib/module/components/ImageGallery/components/ImageGalleryA11yProbe.js.map +1 -0
  26. package/lib/module/components/ImageGallery/hooks/useAnimatedGalleryStyle.js +4 -3
  27. package/lib/module/components/ImageGallery/hooks/useAnimatedGalleryStyle.js.map +1 -1
  28. package/lib/module/components/ImageGallery/hooks/useCurrentImageHeight.js +53 -0
  29. package/lib/module/components/ImageGallery/hooks/useCurrentImageHeight.js.map +1 -0
  30. package/lib/module/components/ImageGallery/hooks/useImageGalleryGestures.js +25 -31
  31. package/lib/module/components/ImageGallery/hooks/useImageGalleryGestures.js.map +1 -1
  32. package/lib/module/state-store/image-gallery-state-store.js +12 -3
  33. package/lib/module/state-store/image-gallery-state-store.js.map +1 -1
  34. package/lib/module/version.json +1 -1
  35. package/lib/typescript/components/ImageGallery/ImageGallery.d.ts.map +1 -1
  36. package/lib/typescript/components/ImageGallery/components/AnimatedGalleryImage.d.ts.map +1 -1
  37. package/lib/typescript/components/ImageGallery/components/AnimatedGalleryVideo.d.ts +1 -4
  38. package/lib/typescript/components/ImageGallery/components/AnimatedGalleryVideo.d.ts.map +1 -1
  39. package/lib/typescript/components/ImageGallery/components/ImageGalleryA11yProbe.d.ts +20 -0
  40. package/lib/typescript/components/ImageGallery/components/ImageGalleryA11yProbe.d.ts.map +1 -0
  41. package/lib/typescript/components/ImageGallery/hooks/useAnimatedGalleryStyle.d.ts +2 -3
  42. package/lib/typescript/components/ImageGallery/hooks/useAnimatedGalleryStyle.d.ts.map +1 -1
  43. package/lib/typescript/components/ImageGallery/hooks/useCurrentImageHeight.d.ts +24 -0
  44. package/lib/typescript/components/ImageGallery/hooks/useCurrentImageHeight.d.ts.map +1 -0
  45. package/lib/typescript/components/ImageGallery/hooks/useImageGalleryGestures.d.ts +1 -1
  46. package/lib/typescript/components/ImageGallery/hooks/useImageGalleryGestures.d.ts.map +1 -1
  47. package/lib/typescript/state-store/image-gallery-state-store.d.ts +8 -0
  48. package/lib/typescript/state-store/image-gallery-state-store.d.ts.map +1 -1
  49. package/package.json +1 -1
  50. package/src/components/ImageGallery/ImageGallery.tsx +41 -120
  51. package/src/components/ImageGallery/__tests__/ImageGallery.test.tsx +4 -1
  52. package/src/components/ImageGallery/__tests__/ImageGalleryAdjustable.test.tsx +5 -4
  53. package/src/components/ImageGallery/components/AnimatedGalleryImage.tsx +9 -11
  54. package/src/components/ImageGallery/components/AnimatedGalleryVideo.tsx +28 -15
  55. package/src/components/ImageGallery/components/ImageGalleryA11yProbe.tsx +82 -0
  56. package/src/components/ImageGallery/hooks/useAnimatedGalleryStyle.tsx +5 -5
  57. package/src/components/ImageGallery/hooks/useCurrentImageHeight.ts +86 -0
  58. package/src/components/ImageGallery/hooks/useImageGalleryGestures.tsx +42 -51
  59. package/src/state-store/__tests__/image-gallery-state-store.test.ts +81 -0
  60. package/src/state-store/image-gallery-state-store.ts +27 -1
  61. package/src/version.json +1 -1
@@ -13,6 +13,7 @@ import { VideoPlayerPool } from '../video-player-pool';
13
13
  jest.mock('../video-player-pool', () => ({
14
14
  VideoPlayerPool: jest.fn().mockImplementation(() => ({
15
15
  clear: jest.fn(),
16
+ getActivePlayer: jest.fn(() => null),
16
17
  pool: new Map(),
17
18
  state: {
18
19
  getLatestValue: () => ({ activeVideoPlayer: null }),
@@ -179,6 +180,63 @@ describe('ImageGalleryStateStore', () => {
179
180
 
180
181
  expect(store.state.getLatestValue().currentIndex).toBe(0);
181
182
  });
183
+
184
+ it('should mirror currentIndex into currentIndexShared.value', () => {
185
+ const store = new ImageGalleryStateStore();
186
+
187
+ store.currentIndex = 7;
188
+
189
+ expect(store.currentIndexShared.value).toBe(7);
190
+ });
191
+
192
+ it('should pause the active video player when currentIndex changes', () => {
193
+ const store = new ImageGalleryStateStore();
194
+ const pause = jest.fn();
195
+ (store.videoPlayerPool.getActivePlayer as jest.Mock).mockReturnValue({ pause });
196
+
197
+ store.currentIndex = 3;
198
+
199
+ expect(pause).toHaveBeenCalledTimes(1);
200
+ });
201
+
202
+ it('should not pause the active player when currentIndex setter is called with the same value', () => {
203
+ const store = new ImageGalleryStateStore();
204
+ store.currentIndex = 3;
205
+ const pause = jest.fn();
206
+ (store.videoPlayerPool.getActivePlayer as jest.Mock).mockReturnValue({ pause });
207
+
208
+ store.currentIndex = 3;
209
+
210
+ expect(pause).not.toHaveBeenCalled();
211
+ });
212
+
213
+ it('should not throw when there is no active player on index change', () => {
214
+ const store = new ImageGalleryStateStore();
215
+ (store.videoPlayerPool.getActivePlayer as jest.Mock).mockReturnValue(null);
216
+
217
+ expect(() => {
218
+ store.currentIndex = 5;
219
+ }).not.toThrow();
220
+ });
221
+ });
222
+
223
+ describe('currentIndexShared mirror', () => {
224
+ it('should initialize at INITIAL_STATE.currentIndex (0)', () => {
225
+ const store = new ImageGalleryStateStore();
226
+
227
+ expect(store.currentIndexShared.value).toBe(0);
228
+ });
229
+
230
+ it('should reset to 0 on clear() even after non-zero set', () => {
231
+ const store = new ImageGalleryStateStore();
232
+ store.currentIndex = 12;
233
+ expect(store.currentIndexShared.value).toBe(12);
234
+
235
+ store.clear();
236
+
237
+ expect(store.state.getLatestValue().currentIndex).toBe(0);
238
+ expect(store.currentIndexShared.value).toBe(0);
239
+ });
182
240
  });
183
241
 
184
242
  describe('attachmentsWithMessage getter', () => {
@@ -707,6 +765,29 @@ describe('ImageGalleryStateStore', () => {
707
765
  unsubscribe();
708
766
  });
709
767
 
768
+ it('should mirror the matched index into currentIndexShared', () => {
769
+ const store = new ImageGalleryStateStore();
770
+ store.subscribeToMessages();
771
+ const unsubscribe = store.subscribeToSelectedAttachmentUrl();
772
+
773
+ store.messages = [
774
+ generateMessage({
775
+ attachments: [generateImageAttachment({ image_url: 'https://example.com/1.jpg' })],
776
+ id: 'msg-1',
777
+ }),
778
+ generateMessage({
779
+ attachments: [generateImageAttachment({ image_url: 'https://example.com/2.jpg' })],
780
+ id: 'msg-2',
781
+ }),
782
+ ];
783
+ store.selectedAttachmentUrl = 'https://example.com/2.jpg';
784
+
785
+ expect(store.state.getLatestValue().currentIndex).toBe(1);
786
+ expect(store.currentIndexShared.value).toBe(1);
787
+
788
+ unsubscribe();
789
+ });
790
+
710
791
  it('should return unsubscribe function', () => {
711
792
  const store = new ImageGalleryStateStore();
712
793
  const unsubscribe = store.subscribeToSelectedAttachmentUrl();
@@ -1,3 +1,5 @@
1
+ import { makeMutable, SharedValue } from 'react-native-reanimated';
2
+
1
3
  import { Attachment, LocalMessage, StateStore, Unsubscribe, UserResponse } from 'stream-chat';
2
4
 
3
5
  import { VideoPlayerPool } from './video-player-pool';
@@ -66,11 +68,19 @@ export class ImageGalleryStateStore {
66
68
  state: StateStore<ImageGalleryState>;
67
69
  options: ImageGalleryOptions;
68
70
  videoPlayerPool: VideoPlayerPool;
71
+ /**
72
+ * SharedValue mirror of `state.currentIndex` for worklet consumers (gesture
73
+ * handlers, animated styles). Maintained in lockstep with the setter and the
74
+ * reset path in `clear()`. Reads from worklets bypass the JS bridge entirely;
75
+ * any code path that updates `currentIndex` must keep this mirror in sync.
76
+ */
77
+ currentIndexShared: SharedValue<number>;
69
78
 
70
79
  constructor(options: Partial<ImageGalleryOptions> = {}) {
71
80
  this.options = { ...INITIAL_IMAGE_GALLERY_OPTIONS, ...options };
72
81
  this.state = new StateStore<ImageGalleryState>(INITIAL_STATE);
73
82
  this.videoPlayerPool = new VideoPlayerPool();
83
+ this.currentIndexShared = makeMutable(INITIAL_STATE.currentIndex);
74
84
  }
75
85
 
76
86
  // Getters
@@ -154,7 +164,21 @@ export class ImageGalleryStateStore {
154
164
  }
155
165
 
156
166
  set currentIndex(currentIndex: number) {
167
+ const previousIndex = this.state.getLatestValue().currentIndex;
157
168
  this.state.partialNext({ currentIndex });
169
+ this.currentIndexShared.value = currentIndex;
170
+ // When the user moves off the current slide, pause whatever video was
171
+ // playing. Moved here from a useEffect in ImageGallery so the invariant
172
+ // lives next to the state it depends on — and the parent no longer needs
173
+ // to subscribe to currentIndex purely to drive this side effect.
174
+ // `clear()` is the other reset path; it bypasses this setter but already
175
+ // pauses everything through `videoPlayerPool.clear()`.
176
+ if (previousIndex !== currentIndex) {
177
+ const activePlayer = this.videoPlayerPool.getActivePlayer();
178
+ if (activePlayer) {
179
+ activePlayer.pause();
180
+ }
181
+ }
158
182
  }
159
183
 
160
184
  set requesterNode(requesterNode: number | null) {
@@ -212,7 +236,8 @@ export class ImageGalleryStateStore {
212
236
  (asset) =>
213
237
  stripQueryFromUrl(asset.uri) === stripQueryFromUrl(selectedAttachmentUrl ?? ''),
214
238
  );
215
- this.state.partialNext({ currentIndex: index === -1 ? 0 : index });
239
+ // Route through the setter so currentIndexShared stays in sync.
240
+ this.currentIndex = index === -1 ? 0 : index;
216
241
  },
217
242
  );
218
243
 
@@ -233,5 +258,6 @@ export class ImageGalleryStateStore {
233
258
  clear = () => {
234
259
  this.videoPlayerPool.clear();
235
260
  this.state.partialNext(INITIAL_STATE);
261
+ this.currentIndexShared.value = INITIAL_STATE.currentIndex;
236
262
  };
237
263
  }
package/src/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "9.4.0-beta.12"
2
+ "version": "9.4.0-beta.13"
3
3
  }