@poolse/react-native 2.13.0 → 2.13.1

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to `@poolse/react-native` are documented here.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
5
5
  versions follow [semver](https://semver.org).
6
6
 
7
+ ## [2.13.1] — 2026-08-23
8
+
9
+ ### Fixed
10
+
11
+ - Controls no longer vanish mid-tap on a video call: pressing one now
12
+ restarts the idle countdown, which a screen-wide handler never saw
13
+ because a child `Pressable` wins the touch outright.
14
+ - The iOS audio policy is released when a call ends while its session is
15
+ still starting, instead of being left installed.
16
+ - The floating self-preview follows the stage across a rotation rather
17
+ than keeping a pixel position from the old bounds.
18
+ - The auto-hang-up on an emptied call fires once rather than on every
19
+ render in the window before the phase flips.
20
+
7
21
  ## [2.13.0] — 2026-08-23
8
22
 
9
23
  A near-total rebuild of the calling surface.
package/dist/index.cjs CHANGED
@@ -5476,6 +5476,11 @@ function LocalVideoPip({
5476
5476
  const cornerRef = react.useRef(corner);
5477
5477
  cornerRef.current = corner;
5478
5478
  const dragged = react.useRef(false);
5479
+ react.useEffect(() => {
5480
+ if (dragged.current) return;
5481
+ const at = corners[corner];
5482
+ if (at) pan.setValue(at);
5483
+ }, [corners, corner, pan]);
5479
5484
  const responder = react.useMemo(
5480
5485
  () => reactNative.PanResponder.create({
5481
5486
  // Claim the gesture only once it is clearly a drag. A lower
@@ -5700,6 +5705,7 @@ function useCallAudio({
5700
5705
  if (!active || !session) return;
5701
5706
  const wantsSpeaker = preferSpeaker.current;
5702
5707
  let disposePolicy;
5708
+ let released = false;
5703
5709
  void (async () => {
5704
5710
  try {
5705
5711
  await session.configureAudio({
@@ -5713,14 +5719,22 @@ function useCallAudio({
5713
5719
  });
5714
5720
  } catch {
5715
5721
  }
5722
+ if (released) return;
5716
5723
  disposePolicy = livekitReactNative?.setupIOSAudioManagement?.(wantsSpeaker);
5717
5724
  try {
5718
5725
  await session.startAudioSession();
5719
5726
  } catch {
5720
5727
  }
5728
+ if (released) {
5729
+ void session.stopAudioSession().catch(() => {
5730
+ });
5731
+ disposePolicy?.();
5732
+ return;
5733
+ }
5721
5734
  refreshRoutes();
5722
5735
  })();
5723
5736
  return () => {
5737
+ released = true;
5724
5738
  void session.stopAudioSession().catch(() => {
5725
5739
  });
5726
5740
  disposePolicy?.();
@@ -5877,31 +5891,33 @@ function CallScreen({
5877
5891
  });
5878
5892
  const [routesOpen, setRoutesOpen] = react.useState(false);
5879
5893
  const [chromeVisible, setChromeVisible] = react.useState(true);
5880
- const hideAt = react.useRef(0);
5894
+ const [lastWake, setLastWake] = react.useState(0);
5881
5895
  const chromeHides = connected && isVideoCall;
5882
5896
  react.useEffect(() => {
5883
- if (!chromeHides) {
5884
- setChromeVisible(true);
5885
- return;
5886
- }
5887
- hideAt.current = Date.now() + CHROME_IDLE_MS;
5888
- const timer = setInterval(() => {
5889
- if (Date.now() >= hideAt.current) setChromeVisible(false);
5890
- }, 500);
5891
- return () => clearInterval(timer);
5892
- }, [chromeHides, chromeVisible]);
5893
- const wakeChrome = react.useCallback(() => {
5894
- hideAt.current = Date.now() + CHROME_IDLE_MS;
5895
5897
  setChromeVisible(true);
5896
- }, []);
5898
+ if (!chromeHides) return;
5899
+ const timer = setTimeout(() => setChromeVisible(false), CHROME_IDLE_MS);
5900
+ return () => clearTimeout(timer);
5901
+ }, [chromeHides, lastWake]);
5902
+ const wakeChrome = react.useCallback(() => setLastWake(Date.now()), []);
5903
+ const withWake = react.useCallback(
5904
+ (fn) => () => {
5905
+ wakeChrome();
5906
+ fn();
5907
+ },
5908
+ [wakeChrome]
5909
+ );
5897
5910
  const hangUp = react.useCallback(() => {
5898
5911
  sfu.leave();
5899
5912
  mesh.leave();
5900
5913
  void calls.hangUp();
5901
5914
  }, [sfu, mesh, calls]);
5902
5915
  const alone = usingSfu ? sfu.alone : mesh.alone;
5916
+ const endedOnEmpty = react.useRef(false);
5917
+ if (calls.phase !== "active") endedOnEmpty.current = false;
5903
5918
  react.useEffect(() => {
5904
- if (!alone || calls.phase !== "active") return;
5919
+ if (!alone || calls.phase !== "active" || endedOnEmpty.current) return;
5920
+ endedOnEmpty.current = true;
5905
5921
  hangUp();
5906
5922
  }, [alone, calls.phase, hangUp]);
5907
5923
  const micOn = usingSfu ? sfu.micEnabled : !mesh.muted;
@@ -6012,7 +6028,7 @@ function CallScreen({
6012
6028
  icon: micOn ? "mic" : "mic-off",
6013
6029
  label: micOn ? "Mute" : "Unmute",
6014
6030
  active: !micOn,
6015
- onPress: toggleMic,
6031
+ onPress: withWake(toggleMic),
6016
6032
  accessibilityLabel: micOn ? "Mute microphone" : "Unmute microphone"
6017
6033
  }
6018
6034
  ),
@@ -6022,7 +6038,7 @@ function CallScreen({
6022
6038
  icon: speakerIcon(audio),
6023
6039
  label: speakerLabel(audio),
6024
6040
  active: audio.speakerOn,
6025
- onPress: onSpeakerPress,
6041
+ onPress: withWake(onSpeakerPress),
6026
6042
  accessibilityLabel: "Audio output"
6027
6043
  }
6028
6044
  ),
@@ -6032,7 +6048,7 @@ function CallScreen({
6032
6048
  icon: videoOn ? "video" : "video-off",
6033
6049
  label: "Camera",
6034
6050
  active: !videoOn,
6035
- onPress: () => void sfu.toggleCamera(),
6051
+ onPress: withWake(() => void sfu.toggleCamera()),
6036
6052
  accessibilityLabel: videoOn ? "Turn camera off" : "Turn camera on"
6037
6053
  }
6038
6054
  ),
@@ -6041,7 +6057,7 @@ function CallScreen({
6041
6057
  {
6042
6058
  icon: "camera-flip",
6043
6059
  label: "Flip",
6044
- onPress: () => void sfu.switchCamera(),
6060
+ onPress: withWake(() => void sfu.switchCamera()),
6045
6061
  accessibilityLabel: "Switch camera"
6046
6062
  }
6047
6063
  )