@repzo/widget-react-native 1.2.2 → 1.3.0

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 (97) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +35 -29
  3. package/android/build.gradle +22 -0
  4. package/android/src/main/java/expo/modules/repzowidget/RepzoVoicePlayer.kt +222 -0
  5. package/android/src/main/java/expo/modules/repzowidget/RepzoWidgetAudioModule.kt +68 -0
  6. package/expo-module.config.json +9 -0
  7. package/ios/RepzoVoicePlayer.swift +175 -0
  8. package/ios/RepzoWidgetAudio.podspec +26 -0
  9. package/ios/RepzoWidgetAudioModule.swift +65 -0
  10. package/lib/commonjs/audio/native-player.js +97 -0
  11. package/lib/commonjs/audio/native-player.js.map +1 -0
  12. package/lib/commonjs/audio/voice.js +34 -7
  13. package/lib/commonjs/audio/voice.js.map +1 -1
  14. package/lib/commonjs/state/widget-store.js +23 -1
  15. package/lib/commonjs/state/widget-store.js.map +1 -1
  16. package/lib/commonjs/ui/WidgetProvider.js +1 -3
  17. package/lib/commonjs/ui/WidgetProvider.js.map +1 -1
  18. package/lib/commonjs/ui/components/ImageViewer.js +17 -35
  19. package/lib/commonjs/ui/components/ImageViewer.js.map +1 -1
  20. package/lib/commonjs/ui/components/MessagesSkeleton.js +126 -0
  21. package/lib/commonjs/ui/components/MessagesSkeleton.js.map +1 -0
  22. package/lib/commonjs/ui/components/VoiceNote.js +8 -9
  23. package/lib/commonjs/ui/components/VoiceNote.js.map +1 -1
  24. package/lib/commonjs/ui/components/ZoomableImage.js +299 -0
  25. package/lib/commonjs/ui/components/ZoomableImage.js.map +1 -0
  26. package/lib/commonjs/ui/screens/chat/ChatView.js +6 -4
  27. package/lib/commonjs/ui/screens/chat/ChatView.js.map +1 -1
  28. package/lib/commonjs/ui/screens/chat/ChatView.styles.js +5 -7
  29. package/lib/commonjs/ui/screens/chat/ChatView.styles.js.map +1 -1
  30. package/lib/module/audio/native-player.js +93 -0
  31. package/lib/module/audio/native-player.js.map +1 -0
  32. package/lib/module/audio/voice.js +32 -6
  33. package/lib/module/audio/voice.js.map +1 -1
  34. package/lib/module/state/widget-store.js +23 -1
  35. package/lib/module/state/widget-store.js.map +1 -1
  36. package/lib/module/ui/WidgetProvider.js +1 -3
  37. package/lib/module/ui/WidgetProvider.js.map +1 -1
  38. package/lib/module/ui/components/ImageViewer.js +18 -36
  39. package/lib/module/ui/components/ImageViewer.js.map +1 -1
  40. package/lib/module/ui/components/MessagesSkeleton.js +124 -0
  41. package/lib/module/ui/components/MessagesSkeleton.js.map +1 -0
  42. package/lib/module/ui/components/VoiceNote.js +9 -10
  43. package/lib/module/ui/components/VoiceNote.js.map +1 -1
  44. package/lib/module/ui/components/ZoomableImage.js +291 -0
  45. package/lib/module/ui/components/ZoomableImage.js.map +1 -0
  46. package/lib/module/ui/screens/chat/ChatView.js +6 -4
  47. package/lib/module/ui/screens/chat/ChatView.js.map +1 -1
  48. package/lib/module/ui/screens/chat/ChatView.styles.js +5 -7
  49. package/lib/module/ui/screens/chat/ChatView.styles.js.map +1 -1
  50. package/lib/typescript/commonjs/audio/native-player.d.ts +36 -0
  51. package/lib/typescript/commonjs/audio/native-player.d.ts.map +1 -0
  52. package/lib/typescript/commonjs/audio/voice.d.ts +17 -4
  53. package/lib/typescript/commonjs/audio/voice.d.ts.map +1 -1
  54. package/lib/typescript/commonjs/state/widget-store.d.ts +11 -0
  55. package/lib/typescript/commonjs/state/widget-store.d.ts.map +1 -1
  56. package/lib/typescript/commonjs/ui/WidgetProvider.d.ts.map +1 -1
  57. package/lib/typescript/commonjs/ui/components/ImageViewer.d.ts +2 -2
  58. package/lib/typescript/commonjs/ui/components/ImageViewer.d.ts.map +1 -1
  59. package/lib/typescript/commonjs/ui/components/MessagesSkeleton.d.ts +10 -0
  60. package/lib/typescript/commonjs/ui/components/MessagesSkeleton.d.ts.map +1 -0
  61. package/lib/typescript/commonjs/ui/components/VoiceNote.d.ts +2 -2
  62. package/lib/typescript/commonjs/ui/components/VoiceNote.d.ts.map +1 -1
  63. package/lib/typescript/commonjs/ui/components/ZoomableImage.d.ts +45 -0
  64. package/lib/typescript/commonjs/ui/components/ZoomableImage.d.ts.map +1 -0
  65. package/lib/typescript/commonjs/ui/screens/chat/ChatView.d.ts.map +1 -1
  66. package/lib/typescript/commonjs/ui/screens/chat/ChatView.styles.d.ts +4 -7
  67. package/lib/typescript/commonjs/ui/screens/chat/ChatView.styles.d.ts.map +1 -1
  68. package/lib/typescript/module/audio/native-player.d.ts +36 -0
  69. package/lib/typescript/module/audio/native-player.d.ts.map +1 -0
  70. package/lib/typescript/module/audio/voice.d.ts +17 -4
  71. package/lib/typescript/module/audio/voice.d.ts.map +1 -1
  72. package/lib/typescript/module/state/widget-store.d.ts +11 -0
  73. package/lib/typescript/module/state/widget-store.d.ts.map +1 -1
  74. package/lib/typescript/module/ui/WidgetProvider.d.ts.map +1 -1
  75. package/lib/typescript/module/ui/components/ImageViewer.d.ts +2 -2
  76. package/lib/typescript/module/ui/components/ImageViewer.d.ts.map +1 -1
  77. package/lib/typescript/module/ui/components/MessagesSkeleton.d.ts +10 -0
  78. package/lib/typescript/module/ui/components/MessagesSkeleton.d.ts.map +1 -0
  79. package/lib/typescript/module/ui/components/VoiceNote.d.ts +2 -2
  80. package/lib/typescript/module/ui/components/VoiceNote.d.ts.map +1 -1
  81. package/lib/typescript/module/ui/components/ZoomableImage.d.ts +45 -0
  82. package/lib/typescript/module/ui/components/ZoomableImage.d.ts.map +1 -0
  83. package/lib/typescript/module/ui/screens/chat/ChatView.d.ts.map +1 -1
  84. package/lib/typescript/module/ui/screens/chat/ChatView.styles.d.ts +4 -7
  85. package/lib/typescript/module/ui/screens/chat/ChatView.styles.d.ts.map +1 -1
  86. package/package.json +10 -3
  87. package/react-native.config.js +12 -0
  88. package/src/audio/native-player.ts +106 -0
  89. package/src/audio/voice.ts +30 -6
  90. package/src/state/widget-store.ts +24 -1
  91. package/src/ui/WidgetProvider.tsx +1 -3
  92. package/src/ui/components/ImageViewer.tsx +11 -30
  93. package/src/ui/components/MessagesSkeleton.tsx +92 -0
  94. package/src/ui/components/VoiceNote.tsx +6 -14
  95. package/src/ui/components/ZoomableImage.tsx +250 -0
  96. package/src/ui/screens/chat/ChatView.styles.ts +5 -7
  97. package/src/ui/screens/chat/ChatView.tsx +4 -3
@@ -0,0 +1,65 @@
1
+ import ExpoModulesCore
2
+
3
+ /**
4
+ * Plays the chat's voice notes, so apps don't need an audio package of their
5
+ * own. JS addresses each note's player by an id it picks (see
6
+ * `src/audio/native-player.ts`); every change comes back as an `onStatus`
7
+ * event carrying that id.
8
+ */
9
+ public class RepzoWidgetAudioModule: Module {
10
+ // Only touched on the main queue: every function below runs there.
11
+ private var players: [String: RepzoVoicePlayer] = [:]
12
+
13
+ public func definition() -> ModuleDefinition {
14
+ Name("RepzoWidgetAudio")
15
+
16
+ Events("onStatus")
17
+
18
+ AsyncFunction("create") { (id: String, url: URL) in
19
+ self.players.removeValue(forKey: id)?.release()
20
+ self.players[id] = RepzoVoicePlayer(url: url) { [weak self] status in
21
+ var body = status
22
+ body["id"] = id
23
+ self?.sendEvent("onStatus", body)
24
+ }
25
+ }.runOnQueue(.main)
26
+
27
+ AsyncFunction("play") { (id: String) in
28
+ self.players[id]?.play()
29
+ }.runOnQueue(.main)
30
+
31
+ AsyncFunction("pause") { (id: String) in
32
+ self.players[id]?.pause()
33
+ }.runOnQueue(.main)
34
+
35
+ AsyncFunction("seekTo") { (id: String, seconds: Double, promise: Promise) in
36
+ guard let player = self.players[id] else {
37
+ promise.resolve(nil)
38
+ return
39
+ }
40
+ player.seek(to: seconds) { promise.resolve(nil) }
41
+ }.runOnQueue(.main)
42
+
43
+ AsyncFunction("setRate") { (id: String, rate: Double) in
44
+ self.players[id]?.setRate(Float(rate))
45
+ }.runOnQueue(.main)
46
+
47
+ AsyncFunction("release") { (id: String) in
48
+ self.players.removeValue(forKey: id)?.release()
49
+ }.runOnQueue(.main)
50
+
51
+ // Leaving the app pauses every note, including one still loading, so it
52
+ // doesn't keep playing with its controls out of sight (apps with the
53
+ // background audio mode would otherwise carry on).
54
+ OnAppEntersBackground {
55
+ self.players.values.forEach { $0.pause() }
56
+ }
57
+
58
+ OnDestroy {
59
+ DispatchQueue.main.async {
60
+ self.players.values.forEach { $0.release() }
61
+ self.players.removeAll()
62
+ }
63
+ }
64
+ }
65
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.hasNativeVoicePlayer = hasNativeVoicePlayer;
7
+ exports.useNativeVoicePlayer = useNativeVoicePlayer;
8
+ var _react = require("react");
9
+ /**
10
+ * The SDK's own voice-note player (`ios/` and `android/`), on the system
11
+ * players: AVPlayer on iOS, MediaPlayer on Android. It's an Expo module, so it
12
+ * exists in apps with Expo modules after a native build; in Expo Go, bare
13
+ * React Native apps and an over-the-air update to an app built with an older
14
+ * SDK it's missing, and `src/audio/voice.ts` falls back to `expo-audio` or the
15
+ * file row.
16
+ */
17
+
18
+ /** What the player reports; the same fields `expo-audio`'s status has. */
19
+
20
+ function loadNativeAudio() {
21
+ let mod = null;
22
+ try {
23
+ mod = require('expo-modules-core').requireOptionalNativeModule('RepzoWidgetAudio');
24
+ } catch {
25
+ mod = null;
26
+ }
27
+ // Without the JS package (an unusual setup), the module can still be installed.
28
+ mod = mod ?? globalThis.expo?.modules?.RepzoWidgetAudio ?? null;
29
+ return mod && typeof mod.create === 'function' && typeof mod.play === 'function' ? mod : null;
30
+ }
31
+ const nativeAudio = loadNativeAudio();
32
+
33
+ /** Subscribes to every player's status; null when events can't be received. */
34
+ function addStatusListener(listener) {
35
+ if (!nativeAudio) return null;
36
+ try {
37
+ if (typeof nativeAudio.addListener === 'function') return nativeAudio.addListener('onStatus', listener);
38
+ // Expo SDK 51 and older: native modules aren't event emitters themselves.
39
+ const {
40
+ EventEmitter
41
+ } = require('expo-modules-core');
42
+ return new EventEmitter(nativeAudio).addListener('onStatus', listener);
43
+ } catch {
44
+ return null;
45
+ }
46
+ }
47
+
48
+ /** Whether the app has the SDK's own player. */
49
+ function hasNativeVoicePlayer() {
50
+ return nativeAudio != null;
51
+ }
52
+ let nextPlayerId = 0;
53
+ const ignore = () => {};
54
+
55
+ /**
56
+ * A player for one note, released when the component goes away. Shaped like
57
+ * `expo-audio`'s `useAudioPlayer` + `useAudioPlayerStatus`, so the voice note
58
+ * drives either the same way.
59
+ */
60
+ function useNativeVoicePlayer(url) {
61
+ const id = (0, _react.useMemo)(() => `repzo-voice-${nextPlayerId += 1}`, []);
62
+ const [status, setStatus] = (0, _react.useState)({
63
+ isLoaded: false
64
+ });
65
+ (0, _react.useEffect)(() => {
66
+ const audio = nativeAudio;
67
+ const subscription = addStatusListener(next => {
68
+ if (next?.id === id) setStatus(next);
69
+ });
70
+ if (!subscription) {
71
+ setStatus({
72
+ isLoaded: false,
73
+ error: 'Voice notes need a newer Expo SDK'
74
+ });
75
+ return undefined;
76
+ }
77
+ audio.create(id, url).catch(error => setStatus({
78
+ isLoaded: false,
79
+ error: String(error)
80
+ }));
81
+ return () => {
82
+ subscription.remove();
83
+ audio.release(id).catch(ignore);
84
+ };
85
+ }, [id, url]);
86
+ const player = (0, _react.useMemo)(() => ({
87
+ play: () => void nativeAudio.play(id).catch(ignore),
88
+ pause: () => void nativeAudio.pause(id).catch(ignore),
89
+ seekTo: seconds => nativeAudio.seekTo(id, seconds).catch(ignore),
90
+ setPlaybackRate: rate => void nativeAudio.setRate(id, rate).catch(ignore)
91
+ }), [id]);
92
+ return {
93
+ player,
94
+ status
95
+ };
96
+ }
97
+ //# sourceMappingURL=native-player.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_react","require","loadNativeAudio","mod","requireOptionalNativeModule","globalThis","expo","modules","RepzoWidgetAudio","create","play","nativeAudio","addStatusListener","listener","addListener","EventEmitter","hasNativeVoicePlayer","nextPlayerId","ignore","useNativeVoicePlayer","url","id","useMemo","status","setStatus","useState","isLoaded","useEffect","audio","subscription","next","error","undefined","catch","String","remove","release","player","pause","seekTo","seconds","setPlaybackRate","rate","setRate"],"sourceRoot":"../../../src","sources":["audio/native-player.ts"],"mappings":"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","ignoreList":[]}
@@ -7,11 +7,16 @@ exports.audioPlayerOptions = audioPlayerOptions;
7
7
  exports.claimVoicePlayback = claimVoicePlayback;
8
8
  exports.formatVoiceClock = formatVoiceClock;
9
9
  exports.isPlayableAudio = isPlayableAudio;
10
- exports.voicePlaybackModule = voicePlaybackModule;
10
+ exports.useVoicePlayer = void 0;
11
+ exports.voicePlaybackBackend = voicePlaybackBackend;
11
12
  exports.voiceWaveformLevels = voiceWaveformLevels;
13
+ var _nativePlayer = require("./native-player.js");
12
14
  /**
13
- * Voice notes (and any audio file) play inside the chat when the host app has
14
- * `expo-audio`; without it they stay a file row that opens in the browser.
15
+ * Voice notes (and any audio file) play inside the chat with the SDK's own
16
+ * native player (`src/audio/native-player.ts`). Where that isn't built into
17
+ * the app (Expo Go, bare React Native, an app built with SDK 1.2.2 or older),
18
+ * they play with the host app's `expo-audio` if it has one; otherwise they
19
+ * stay a file row that opens in the browser.
15
20
  *
16
21
  * Resolved once at module load, like the attachment pickers: each `require` is
17
22
  * static so Metro can see it, and with `allowOptionalDependencies` (see
@@ -42,9 +47,10 @@ try {
42
47
  /** How often the playhead moves while a note plays. */
43
48
  const UPDATE_INTERVAL_MS = 100;
44
49
 
45
- /** The installed expo-audio module, or null when the app doesn't have it. */
46
- function voicePlaybackModule() {
47
- return expoAudio;
50
+ /** Which player voice notes use in this app, or null when audio stays a file row. */
51
+ const backend = (0, _nativePlayer.hasNativeVoicePlayer)() ? 'native' : expoAudio ? 'expo-audio' : null;
52
+ function voicePlaybackBackend() {
53
+ return backend;
48
54
  }
49
55
 
50
56
  /** The second argument to `useAudioPlayer` for the installed expo-audio. */
@@ -54,9 +60,30 @@ function audioPlayerOptions() {
54
60
  } : UPDATE_INTERVAL_MS;
55
61
  }
56
62
 
63
+ /** expo-audio's player for a note, on the same terms as the native one. */
64
+ function useExpoAudioPlayer(url) {
65
+ const player = expoAudio.useAudioPlayer({
66
+ uri: url
67
+ }, audioPlayerOptions());
68
+ const status = expoAudio.useAudioPlayerStatus(player);
69
+ return {
70
+ player,
71
+ status
72
+ };
73
+ }
74
+
75
+ /**
76
+ * The player for one note: `play()`, `pause()`, `seekTo(seconds)`,
77
+ * `setPlaybackRate(rate)`, and its status (`currentTime`, `duration`,
78
+ * `playing`, `isLoaded`, `isBuffering`, `didJustFinish`, `error`). Only use it
79
+ * when `voicePlaybackBackend()` isn't null. Picked once, since the backend
80
+ * never changes while the app runs.
81
+ */
82
+ const useVoicePlayer = exports.useVoicePlayer = backend === 'native' ? _nativePlayer.useNativeVoicePlayer : useExpoAudioPlayer;
83
+
57
84
  /** Audio the chat can play in place: an `audio/*` attachment with a web address. */
58
85
  function isPlayableAudio(contentType, url) {
59
- return !!expoAudio && (contentType ?? '').toLowerCase().startsWith('audio/') && /^https?:\/\//i.test(url ?? '');
86
+ return backend != null && (contentType ?? '').toLowerCase().startsWith('audio/') && /^https?:\/\//i.test(url ?? '');
60
87
  }
61
88
 
62
89
  // ─── One note at a time ─────────────────────────────────────────────────────
@@ -1 +1 @@
1
- {"version":3,"names":["expoAudio","mod","require","useAudioPlayer","useAudioPlayerStatus","takesOptionsObject","version","Number","split","UPDATE_INTERVAL_MS","voicePlaybackModule","audioPlayerOptions","updateInterval","isPlayableAudio","contentType","url","toLowerCase","startsWith","test","playing","claimVoicePlayback","pause","claim","previous","voiceWaveformLevels","seed","count","h","i","length","charCodeAt","Math","imul","levels","n","push","pow","formatVoiceClock","seconds","s","max","floor","isFinite","toString","padStart"],"sourceRoot":"../../../src","sources":["audio/voice.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_nativePlayer","require","expoAudio","mod","useAudioPlayer","useAudioPlayerStatus","takesOptionsObject","version","Number","split","UPDATE_INTERVAL_MS","backend","hasNativeVoicePlayer","voicePlaybackBackend","audioPlayerOptions","updateInterval","useExpoAudioPlayer","url","player","uri","status","useVoicePlayer","exports","useNativeVoicePlayer","isPlayableAudio","contentType","toLowerCase","startsWith","test","playing","claimVoicePlayback","pause","claim","previous","voiceWaveformLevels","seed","count","h","i","length","charCodeAt","Math","imul","levels","n","push","pow","formatVoiceClock","seconds","s","max","floor","isFinite","toString","padStart"],"sourceRoot":"../../../src","sources":["audio/voice.ts"],"mappings":"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","ignoreList":[]}
@@ -25,7 +25,7 @@ var _safeUrl = require("../ui/utils/safe-url.js");
25
25
  */
26
26
 
27
27
  /** Sent on every init; must match `package.json` (tests/version.test.js checks). */
28
- const SDK_VERSION = '@repzo/widget-react-native@1.2.2';
28
+ const SDK_VERSION = '@repzo/widget-react-native@1.3.0';
29
29
 
30
30
  /** The platform this session reports — mobile sessions get the Mobile SDKs overrides. */
31
31
  function sessionPlatform() {
@@ -171,6 +171,13 @@ class WidgetStore {
171
171
  /** True once `currentUserKey` mirrors storage — memory is then authoritative. */
172
172
  userKeyLoaded = false;
173
173
  pendingConversationId = null;
174
+
175
+ /**
176
+ * The screen a thread was opened from, so its back button returns there.
177
+ * Null when it was opened with the messenger closed (a push, a notification
178
+ * card, `presentConversation`): there is nothing to go back to.
179
+ */
180
+ chatOpenedFrom = null;
174
181
  appStateSubscription = null;
175
182
 
176
183
  /** When the app last went to the background (0: hasn't this session). */
@@ -269,6 +276,13 @@ class WidgetStore {
269
276
  next.inAppNotification = null;
270
277
  }
271
278
  this.state = next;
279
+
280
+ // Recorded here because a thread opens from many places (home cards, the
281
+ // list, the Messages tab, posts) and each would otherwise have to say so.
282
+ const intoThread = next.view === 'chat' || next.view === 'prechat';
283
+ if (intoThread && previous.view !== 'chat' && previous.view !== 'prechat') {
284
+ this.chatOpenedFrom = previous.isOpen && (previous.view === 'home' || previous.view === 'conversations') ? previous.view : null;
285
+ }
272
286
  if (next.unreadCount !== previous.unreadCount) {
273
287
  this.events.emit(_events.RepzoWidgetEvents.UnreadCountDidChange, {
274
288
  count: next.unreadCount
@@ -1400,6 +1414,14 @@ class WidgetStore {
1400
1414
  } : {})
1401
1415
  });
1402
1416
  }
1417
+
1418
+ /**
1419
+ * The thread's back button: the screen it was opened from, or the
1420
+ * conversation list when it was opened from outside the messenger.
1421
+ */
1422
+ leaveConversation() {
1423
+ this.setView(this.chatOpenedFrom ?? (this.state.activeTab === 'messages' ? 'conversations' : 'home'));
1424
+ }
1403
1425
  setActiveTab(tab) {
1404
1426
  if (tab === 'home') {
1405
1427
  this.setState({