@naviedu/room-platform-react 0.0.35 → 0.0.36

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/README.md CHANGED
@@ -97,6 +97,9 @@ stage keeps its waiting state and never promotes a student camera. The local
97
97
  sidebar preview is hidden only when that selected moderator camera is local;
98
98
  its existing desktop breakpoint remains unchanged.
99
99
 
100
+ The public room keeps one canonical local camera track. It may be preview-only
101
+ before publication, and preview visibility never grants `media:publish_video`.
102
+
100
103
  ### Error and lifecycle callbacks
101
104
 
102
105
  ```tsx
package/index.d.ts CHANGED
@@ -260,7 +260,6 @@ declare type RoomPlatformContextValue = {
260
260
  isActionPending: (name: RoomPlatformActionName, payload?: Record<string, string>) => boolean;
261
261
  isLocalMediaPending: (kind: RoomPlatformLocalMediaKind) => boolean;
262
262
  localCameraTrack: LocalVideoTrack | null;
263
- localPreviewTrack: LocalVideoTrack | null;
264
263
  localMedia: RoomPlatformLocalMediaState;
265
264
  performAction: (name: RoomPlatformActionName, payload?: Record<string, string>) => Promise<void>;
266
265
  room: Room | null;
@@ -398,9 +397,9 @@ export declare type RoomPlatformLocalMediaKind = 'microphone' | 'camera' | 'scre
398
397
 
399
398
  declare type RoomPlatformLocalMediaState = Record<RoomPlatformLocalMediaKind, boolean>;
400
399
 
401
- export declare function RoomPlatformLocalPreview({ trackRef, localPreviewTrack, }: {
400
+ export declare function RoomPlatformLocalPreview({ trackRef, localTrack, }: {
402
401
  trackRef?: TrackReference;
403
- localPreviewTrack?: LocalVideoTrack | null;
402
+ localTrack?: LocalVideoTrack | null;
404
403
  }): JSX.Element;
405
404
 
406
405
  export declare function RoomPlatformMediaRuntime({ children }: PropsWithChildren): JSX.Element;
package/index.esm.js CHANGED
@@ -3,7 +3,7 @@ import * as React from 'react';
3
3
  import { Component, useContext, createContext, forwardRef, useState, useRef, useEffect, useLayoutEffect, useMemo, useCallback, useId } from 'react';
4
4
  import { Slot, AlertDialog as AlertDialog$1, Dialog as Dialog$1, Select as Select$1, Tabs as Tabs$1, Tooltip as Tooltip$1 } from 'radix-ui';
5
5
  import { Minimize2, Maximize2, XIcon, ChevronDownIcon, CheckIcon, ChevronUpIcon, Loader2Icon, PhoneOff, Bell, PhoneCall, Hand, VideoOff, ChevronUp, SunDim, Images, ImageUp, Plus, Trash2, Settings, ArrowLeftRight, Monitor, LogOut, Mic, Camera, X, ChevronLeft, ChevronRight, PanelRightOpen, PanelRightClose, Power, Check } from 'lucide-react';
6
- import { RoomEvent, Track, createLocalVideoTrack, Room, DataPacket_Kind } from 'livekit-client';
6
+ import { TrackEvent, RoomEvent, createLocalVideoTrack, Track, Room, DataPacket_Kind } from 'livekit-client';
7
7
  import { io } from 'socket.io-client';
8
8
  import { createPortal } from 'react-dom';
9
9
  import { toast, Toaster } from 'sonner';
@@ -13934,6 +13934,9 @@ var localMediaCapabilities = {
13934
13934
  camera: 'media:publish_video',
13935
13935
  screenShare: 'media:share_screen'
13936
13936
  };
13937
+ var canPreviewCamera = function(capabilities) {
13938
+ return capabilities.includes('media:publish_video') || capabilities.includes('room:speak_request');
13939
+ };
13937
13940
  var RoomPlatformContext = /*#__PURE__*/ createContext(undefined);
13938
13941
  var emptyLocalMediaState = {
13939
13942
  camera: false,
@@ -14041,13 +14044,6 @@ var localMediaStateOf = function(room) {
14041
14044
  screenShare: room.localParticipant.isScreenShareEnabled
14042
14045
  };
14043
14046
  };
14044
- var localCameraTrackOf = function(room) {
14045
- var _ref;
14046
- var _getTrackPublication_call;
14047
- var getTrackPublication = room.localParticipant.getTrackPublication;
14048
- if (typeof getTrackPublication !== 'function') return null;
14049
- return (_ref = (_getTrackPublication_call = getTrackPublication.call(room.localParticipant, Track.Source.Camera)) === null || _getTrackPublication_call === void 0 ? void 0 : _getTrackPublication_call.track) !== null && _ref !== void 0 ? _ref : null;
14050
- };
14051
14047
  var roleFromMetadata = function(metadata) {
14052
14048
  try {
14053
14049
  var parsed = JSON.parse(metadata !== null && metadata !== void 0 ? metadata : '{}');
@@ -14080,16 +14076,15 @@ function RoomPlatformProvider(param) {
14080
14076
  var _useState3 = _sliced_to_array$o(useState(), 2), controlState = _useState3[0], setControlState = _useState3[1];
14081
14077
  var _useState4 = _sliced_to_array$o(useState(), 2), error = _useState4[0], setError = _useState4[1];
14082
14078
  var _useState5 = _sliced_to_array$o(useState(null), 2), localCameraTrack = _useState5[0], setLocalCameraTrack = _useState5[1];
14083
- var _useState6 = _sliced_to_array$o(useState(null), 2), localPreviewTrack = _useState6[0], setLocalPreviewTrack = _useState6[1];
14084
- var _useState7 = _sliced_to_array$o(useState(emptyLocalMediaState), 2), localMedia = _useState7[0], setLocalMedia = _useState7[1];
14085
- var _useState8 = _sliced_to_array$o(useState(null), 2), integrations = _useState8[0], setIntegrations = _useState8[1];
14086
- var _useState9 = _sliced_to_array$o(useState(), 2), privateRoom = _useState9[0], setPrivateRoom = _useState9[1];
14087
- var _useState10 = _sliced_to_array$o(useState(), 2), privateRoomConnection = _useState10[0], setPrivateRoomConnection = _useState10[1];
14088
- var _useState11 = _sliced_to_array$o(useState(false), 2), privateMediaRestorePending = _useState11[0], setPrivateMediaRestorePending = _useState11[1];
14089
- var _useState12 = _sliced_to_array$o(useState([]), 2), pendingActionKeys = _useState12[0], setPendingActionKeys = _useState12[1];
14090
- var _useState13 = _sliced_to_array$o(useState([]), 2), pendingLocalMediaKinds = _useState13[0], setPendingLocalMediaKinds = _useState13[1];
14091
- var _useState14 = _sliced_to_array$o(useState(null), 2), room = _useState14[0], setRoom = _useState14[1];
14092
- var _useState15 = _sliced_to_array$o(useState('connecting'), 2), status = _useState15[0], setStatus = _useState15[1];
14079
+ var _useState6 = _sliced_to_array$o(useState(emptyLocalMediaState), 2), localMedia = _useState6[0], setLocalMedia = _useState6[1];
14080
+ var _useState7 = _sliced_to_array$o(useState(null), 2), integrations = _useState7[0], setIntegrations = _useState7[1];
14081
+ var _useState8 = _sliced_to_array$o(useState(), 2), privateRoom = _useState8[0], setPrivateRoom = _useState8[1];
14082
+ var _useState9 = _sliced_to_array$o(useState(), 2), privateRoomConnection = _useState9[0], setPrivateRoomConnection = _useState9[1];
14083
+ var _useState10 = _sliced_to_array$o(useState(false), 2), privateMediaRestorePending = _useState10[0], setPrivateMediaRestorePending = _useState10[1];
14084
+ var _useState11 = _sliced_to_array$o(useState([]), 2), pendingActionKeys = _useState11[0], setPendingActionKeys = _useState11[1];
14085
+ var _useState12 = _sliced_to_array$o(useState([]), 2), pendingLocalMediaKinds = _useState12[0], setPendingLocalMediaKinds = _useState12[1];
14086
+ var _useState13 = _sliced_to_array$o(useState(null), 2), room = _useState13[0], setRoom = _useState13[1];
14087
+ var _useState14 = _sliced_to_array$o(useState('connecting'), 2), status = _useState14[0], setStatus = _useState14[1];
14093
14088
  var isMountedRef = useRef(false);
14094
14089
  var accessRef = useRef(undefined);
14095
14090
  var controlStateRef = useRef(undefined);
@@ -14099,7 +14094,14 @@ function RoomPlatformProvider(param) {
14099
14094
  var pendingActionsRef = useRef(new Map());
14100
14095
  var pendingLocalMediaRef = useRef(new Map());
14101
14096
  var hasFirstSuccessfulConnectionRef = useRef(false);
14102
- var localPreviewTrackRef = useRef(null);
14097
+ var cameraDesiredRef = useRef(false);
14098
+ var canonicalCameraTrackRef = useRef(null);
14099
+ var cameraTrackEndedHandlerRef = useRef(undefined);
14100
+ var cameraCreationRef = useRef(undefined);
14101
+ var cameraTransitionRef = useRef(Promise.resolve());
14102
+ var cameraRevisionRef = useRef(0);
14103
+ var accessGenerationRef = useRef(0);
14104
+ var handleCameraEndedRef = useRef(undefined);
14103
14105
  var initialLaunchTokenRef = useRef(launchToken);
14104
14106
  var recoveryRef = useRef(undefined);
14105
14107
  var roomConnectionRef = useRef(null);
@@ -14119,9 +14121,15 @@ function RoomPlatformProvider(param) {
14119
14121
  var onErrorRef = useRef(onError);
14120
14122
  var onLifecycleEventRef = useRef(onLifecycleEvent);
14121
14123
  var onLaunchTicketRequiredRef = useRef(onLaunchTicketRequired);
14122
- onErrorRef.current = onError;
14123
- onLifecycleEventRef.current = onLifecycleEvent;
14124
- onLaunchTicketRequiredRef.current = onLaunchTicketRequired;
14124
+ useEffect(function() {
14125
+ onErrorRef.current = onError;
14126
+ onLifecycleEventRef.current = onLifecycleEvent;
14127
+ onLaunchTicketRequiredRef.current = onLaunchTicketRequired;
14128
+ }, [
14129
+ onError,
14130
+ onLaunchTicketRequired,
14131
+ onLifecycleEvent
14132
+ ]);
14125
14133
  var isLifecycleActive = useCallback(function(lifecycle) {
14126
14134
  return isMountedRef.current && lifecycleRef.current === lifecycle;
14127
14135
  }, []);
@@ -14181,21 +14189,23 @@ function RoomPlatformProvider(param) {
14181
14189
  }, []);
14182
14190
  var syncControlState = useCallback(function() {
14183
14191
  return _async_to_generator$k(function() {
14184
- var sync;
14192
+ var currentAccess, generation, inFlight, sync, _controlStateSyncRef_current;
14185
14193
  return _ts_generator$k(this, function(_state) {
14186
14194
  switch(_state.label){
14187
14195
  case 0:
14188
- if (controlStateSyncRef.current !== undefined) return [
14196
+ currentAccess = accessRef.current;
14197
+ generation = accessGenerationRef.current;
14198
+ inFlight = controlStateSyncRef.current;
14199
+ if ((inFlight === null || inFlight === void 0 ? void 0 : inFlight.generation) === generation) return [
14189
14200
  2,
14190
- controlStateSyncRef.current
14201
+ inFlight.promise
14191
14202
  ];
14192
14203
  sync = function() {
14193
14204
  return _async_to_generator$k(function() {
14194
- var currentAccess, response, body, syncError;
14205
+ var response, body, syncError;
14195
14206
  return _ts_generator$k(this, function(_state) {
14196
14207
  switch(_state.label){
14197
14208
  case 0:
14198
- currentAccess = accessRef.current;
14199
14209
  if (!currentAccess) return [
14200
14210
  2,
14201
14211
  false
@@ -14237,7 +14247,7 @@ function RoomPlatformProvider(param) {
14237
14247
  body = unwrapGatewayResponse.apply(void 0, [
14238
14248
  _state.sent()
14239
14249
  ]);
14240
- if (body.roomId === currentAccess.roomId) {
14250
+ if (accessRef.current === currentAccess && accessGenerationRef.current === generation && body.roomId === currentAccess.roomId) {
14241
14251
  applyPrivateRoomProjection(body, true);
14242
14252
  applyControlState(body.state, true);
14243
14253
  return [
@@ -14251,7 +14261,7 @@ function RoomPlatformProvider(param) {
14251
14261
  ];
14252
14262
  case 6:
14253
14263
  syncError = _state.sent();
14254
- reportError(syncError, {
14264
+ if (accessRef.current === currentAccess && accessGenerationRef.current === generation) reportError(syncError, {
14255
14265
  recoverable: true,
14256
14266
  scope: 'connection'
14257
14267
  });
@@ -14268,7 +14278,10 @@ function RoomPlatformProvider(param) {
14268
14278
  });
14269
14279
  })();
14270
14280
  }();
14271
- controlStateSyncRef.current = sync;
14281
+ controlStateSyncRef.current = {
14282
+ generation: generation,
14283
+ promise: sync
14284
+ };
14272
14285
  _state.label = 1;
14273
14286
  case 1:
14274
14287
  _state.trys.push([
@@ -14287,7 +14300,7 @@ function RoomPlatformProvider(param) {
14287
14300
  _state.sent()
14288
14301
  ];
14289
14302
  case 3:
14290
- if (controlStateSyncRef.current === sync) controlStateSyncRef.current = undefined;
14303
+ if (((_controlStateSyncRef_current = controlStateSyncRef.current) === null || _controlStateSyncRef_current === void 0 ? void 0 : _controlStateSyncRef_current.promise) === sync) controlStateSyncRef.current = undefined;
14291
14304
  return [
14292
14305
  7
14293
14306
  ];
@@ -14304,6 +14317,494 @@ function RoomPlatformProvider(param) {
14304
14317
  applyPrivateRoomProjection,
14305
14318
  reportError
14306
14319
  ]);
14320
+ var enqueueCameraTransition = useCallback(function(transition) {
14321
+ var next = cameraTransitionRef.current.then(transition, transition);
14322
+ cameraTransitionRef.current = next.catch(function() {
14323
+ return undefined;
14324
+ });
14325
+ return next;
14326
+ }, []);
14327
+ var cameraRoomIsPrivate = useCallback(function(currentRoom) {
14328
+ var actorId = externalActorIdFromMetadata$2(currentRoom.localParticipant.metadata);
14329
+ var currentPrivateRoom = privateRoomRef.current;
14330
+ return Boolean((currentPrivateRoom === null || currentPrivateRoom === void 0 ? void 0 : currentPrivateRoom.status) === 'active' && actorId && (currentPrivateRoom.callerExternalActorId === actorId || currentPrivateRoom.studentExternalActorId === actorId));
14331
+ }, []);
14332
+ var cameraShouldBeForced = useCallback(function(currentRoom) {
14333
+ var _controlStateRef_current;
14334
+ return ((_controlStateRef_current = controlStateRef.current) === null || _controlStateRef_current === void 0 ? void 0 : _controlStateRef_current.monitorActive) === true && roleFromMetadata(currentRoom.localParticipant.metadata) === 'student';
14335
+ }, []);
14336
+ var cameraCanPublish = useCallback(function(currentRoom, currentAccess) {
14337
+ var _controlStateRef_current;
14338
+ var activeSpeaker = ((_controlStateRef_current = controlStateRef.current) === null || _controlStateRef_current === void 0 ? void 0 : _controlStateRef_current.activeSpeakerParticipantIdentity) === currentAccess.liveKit.participantIdentity;
14339
+ return currentAccess.capabilities.includes(localMediaCapabilities.camera) || activeSpeaker || cameraShouldBeForced(currentRoom);
14340
+ }, [
14341
+ cameraShouldBeForced
14342
+ ]);
14343
+ var cameraShouldCapture = useCallback(function(currentRoom, currentAccess) {
14344
+ return !cameraRoomIsPrivate(currentRoom) && (cameraShouldBeForced(currentRoom) || cameraDesiredRef.current && canPreviewCamera(currentAccess.capabilities));
14345
+ }, [
14346
+ cameraRoomIsPrivate,
14347
+ cameraShouldBeForced
14348
+ ]);
14349
+ var cameraShouldPublish = useCallback(function(currentRoom, currentAccess) {
14350
+ return cameraShouldCapture(currentRoom, currentAccess) && cameraCanPublish(currentRoom, currentAccess);
14351
+ }, [
14352
+ cameraCanPublish,
14353
+ cameraShouldCapture
14354
+ ]);
14355
+ var removeCanonicalCameraTrack = useCallback(function(track, stop) {
14356
+ if (cameraTrackEndedHandlerRef.current) track.off(TrackEvent.Ended, cameraTrackEndedHandlerRef.current);
14357
+ cameraTrackEndedHandlerRef.current = undefined;
14358
+ if (canonicalCameraTrackRef.current === track) canonicalCameraTrackRef.current = null;
14359
+ if (stop) track.stop();
14360
+ if (isMountedRef.current) {
14361
+ setLocalCameraTrack(null);
14362
+ setLocalMedia(function(current) {
14363
+ return _object_spread_props$b(_object_spread$d({}, current), {
14364
+ camera: false
14365
+ });
14366
+ });
14367
+ }
14368
+ }, []);
14369
+ var ensureLocalCameraTrack = useCallback(function(lifecycle, revision, generation, currentRoom) {
14370
+ var _roomConnectionRef_current;
14371
+ var existing = canonicalCameraTrackRef.current;
14372
+ if (existing) return Promise.resolve(existing);
14373
+ var currentAccess = accessRef.current;
14374
+ if (!isLifecycleActive(lifecycle) || !currentAccess || !cameraShouldCapture(currentRoom, currentAccess) || ((_roomConnectionRef_current = roomConnectionRef.current) === null || _roomConnectionRef_current === void 0 ? void 0 : _roomConnectionRef_current.room) !== currentRoom) return Promise.resolve(null);
14375
+ var pendingCreation = cameraCreationRef.current;
14376
+ if (pendingCreation !== undefined) return pendingCreation.then(function(track) {
14377
+ if (track) return track;
14378
+ if (cameraCreationRef.current === pendingCreation) cameraCreationRef.current = undefined;
14379
+ return null;
14380
+ });
14381
+ var creation = function() {
14382
+ return _async_to_generator$k(function() {
14383
+ var _roomConnectionRef_current, created, stillCurrent, ended, creationError;
14384
+ return _ts_generator$k(this, function(_state) {
14385
+ switch(_state.label){
14386
+ case 0:
14387
+ _state.trys.push([
14388
+ 0,
14389
+ 2,
14390
+ ,
14391
+ 3
14392
+ ]);
14393
+ return [
14394
+ 4,
14395
+ createLocalVideoTrack()
14396
+ ];
14397
+ case 1:
14398
+ created = _state.sent();
14399
+ stillCurrent = isLifecycleActive(lifecycle) && cameraRevisionRef.current === revision && accessGenerationRef.current === generation && ((_roomConnectionRef_current = roomConnectionRef.current) === null || _roomConnectionRef_current === void 0 ? void 0 : _roomConnectionRef_current.room) === currentRoom && accessRef.current !== undefined && cameraShouldCapture(currentRoom, accessRef.current);
14400
+ if (!stillCurrent) {
14401
+ created.stop();
14402
+ return [
14403
+ 2,
14404
+ null
14405
+ ];
14406
+ }
14407
+ ended = function() {
14408
+ for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
14409
+ args[_key] = arguments[_key];
14410
+ }
14411
+ if (args.length > 0 && args[0] !== created) return;
14412
+ void enqueueCameraTransition(function() {
14413
+ var _ref;
14414
+ var _handleCameraEndedRef_current;
14415
+ return (_ref = (_handleCameraEndedRef_current = handleCameraEndedRef.current) === null || _handleCameraEndedRef_current === void 0 ? void 0 : _handleCameraEndedRef_current.call(handleCameraEndedRef, lifecycle, created)) !== null && _ref !== void 0 ? _ref : Promise.resolve();
14416
+ });
14417
+ };
14418
+ canonicalCameraTrackRef.current = created;
14419
+ cameraTrackEndedHandlerRef.current = ended;
14420
+ created.on(TrackEvent.Ended, ended);
14421
+ if (isMountedRef.current) setLocalCameraTrack(created);
14422
+ return [
14423
+ 2,
14424
+ created
14425
+ ];
14426
+ case 2:
14427
+ creationError = _state.sent();
14428
+ reportError(creationError, {
14429
+ recoverable: true,
14430
+ scope: 'media'
14431
+ });
14432
+ return [
14433
+ 2,
14434
+ null
14435
+ ];
14436
+ case 3:
14437
+ return [
14438
+ 2
14439
+ ];
14440
+ }
14441
+ });
14442
+ })();
14443
+ }();
14444
+ cameraCreationRef.current = creation;
14445
+ void creation.then(function() {
14446
+ if (cameraCreationRef.current === creation) cameraCreationRef.current = undefined;
14447
+ }, function() {
14448
+ if (cameraCreationRef.current === creation) cameraCreationRef.current = undefined;
14449
+ });
14450
+ return creation;
14451
+ }, [
14452
+ cameraShouldCapture,
14453
+ enqueueCameraTransition,
14454
+ isLifecycleActive,
14455
+ reportError
14456
+ ]);
14457
+ var unpublishCanonicalCamera = useCallback(function(retainForPreview) {
14458
+ return _async_to_generator$k(function() {
14459
+ var _roomConnectionRef_current, currentRoom, track, publication, wasPublished, unpublishError;
14460
+ return _ts_generator$k(this, function(_state) {
14461
+ switch(_state.label){
14462
+ case 0:
14463
+ currentRoom = (_roomConnectionRef_current = roomConnectionRef.current) === null || _roomConnectionRef_current === void 0 ? void 0 : _roomConnectionRef_current.room;
14464
+ track = canonicalCameraTrackRef.current;
14465
+ if (!currentRoom || !track) return [
14466
+ 2
14467
+ ];
14468
+ publication = currentRoom.localParticipant.getTrackPublication(Track.Source.Camera);
14469
+ wasPublished = (publication === null || publication === void 0 ? void 0 : publication.track) === track;
14470
+ _state.label = 1;
14471
+ case 1:
14472
+ _state.trys.push([
14473
+ 1,
14474
+ 4,
14475
+ ,
14476
+ 5
14477
+ ]);
14478
+ if (!wasPublished) return [
14479
+ 3,
14480
+ 3
14481
+ ];
14482
+ return [
14483
+ 4,
14484
+ currentRoom.localParticipant.unpublishTrack(track, !retainForPreview)
14485
+ ];
14486
+ case 2:
14487
+ _state.sent();
14488
+ _state.label = 3;
14489
+ case 3:
14490
+ return [
14491
+ 3,
14492
+ 5
14493
+ ];
14494
+ case 4:
14495
+ unpublishError = _state.sent();
14496
+ if (!retainForPreview) removeCanonicalCameraTrack(track, true);
14497
+ reportError(unpublishError, {
14498
+ recoverable: true,
14499
+ scope: 'media'
14500
+ });
14501
+ return [
14502
+ 2
14503
+ ];
14504
+ case 5:
14505
+ if (!retainForPreview) removeCanonicalCameraTrack(track, !wasPublished);
14506
+ else if (isMountedRef.current) setLocalMedia(function(current) {
14507
+ return _object_spread_props$b(_object_spread$d({}, current), {
14508
+ camera: false
14509
+ });
14510
+ });
14511
+ return [
14512
+ 2
14513
+ ];
14514
+ }
14515
+ });
14516
+ })();
14517
+ }, [
14518
+ removeCanonicalCameraTrack,
14519
+ reportError
14520
+ ]);
14521
+ var publishCanonicalCamera = useCallback(function(lifecycle, revision, generation, currentRoom) {
14522
+ return _async_to_generator$k(function() {
14523
+ var _roomConnectionRef_current, currentAccess, track, publication, _roomConnectionRef_current1, latestAccess, canRetainForPreview, publication1, wasPublished, publishError, _roomConnectionRef_current2, latestAccess1, canRetain;
14524
+ return _ts_generator$k(this, function(_state) {
14525
+ switch(_state.label){
14526
+ case 0:
14527
+ currentAccess = accessRef.current;
14528
+ track = canonicalCameraTrackRef.current;
14529
+ if (!track || !currentAccess) return [
14530
+ 2
14531
+ ];
14532
+ if (!isLifecycleActive(lifecycle) || cameraRevisionRef.current !== revision || accessGenerationRef.current !== generation || ((_roomConnectionRef_current = roomConnectionRef.current) === null || _roomConnectionRef_current === void 0 ? void 0 : _roomConnectionRef_current.room) !== currentRoom || !cameraShouldPublish(currentRoom, currentAccess)) return [
14533
+ 2
14534
+ ];
14535
+ publication = currentRoom.localParticipant.getTrackPublication(Track.Source.Camera);
14536
+ if ((publication === null || publication === void 0 ? void 0 : publication.track) === track) return [
14537
+ 2
14538
+ ];
14539
+ _state.label = 1;
14540
+ case 1:
14541
+ _state.trys.push([
14542
+ 1,
14543
+ 7,
14544
+ ,
14545
+ 8
14546
+ ]);
14547
+ return [
14548
+ 4,
14549
+ currentRoom.localParticipant.publishTrack(track)
14550
+ ];
14551
+ case 2:
14552
+ _state.sent();
14553
+ latestAccess = accessRef.current;
14554
+ canRetainForPreview = Boolean(latestAccess && cameraDesiredRef.current && canPreviewCamera(latestAccess.capabilities) && cameraShouldCapture(currentRoom, latestAccess));
14555
+ if (!(latestAccess && isLifecycleActive(lifecycle) && cameraRevisionRef.current === revision && accessGenerationRef.current === generation && !cameraShouldPublish(currentRoom, latestAccess))) return [
14556
+ 3,
14557
+ 4
14558
+ ];
14559
+ return [
14560
+ 4,
14561
+ unpublishCanonicalCamera(canRetainForPreview)
14562
+ ];
14563
+ case 3:
14564
+ _state.sent();
14565
+ return [
14566
+ 2
14567
+ ];
14568
+ case 4:
14569
+ if (!(!isLifecycleActive(lifecycle) || cameraRevisionRef.current !== revision || accessGenerationRef.current !== generation || ((_roomConnectionRef_current1 = roomConnectionRef.current) === null || _roomConnectionRef_current1 === void 0 ? void 0 : _roomConnectionRef_current1.room) !== currentRoom)) return [
14570
+ 3,
14571
+ 6
14572
+ ];
14573
+ publication1 = currentRoom.localParticipant.getTrackPublication(Track.Source.Camera);
14574
+ wasPublished = (publication1 === null || publication1 === void 0 ? void 0 : publication1.track) === track;
14575
+ return [
14576
+ 4,
14577
+ currentRoom.localParticipant.unpublishTrack(track, !canRetainForPreview)
14578
+ ];
14579
+ case 5:
14580
+ _state.sent();
14581
+ if (!canRetainForPreview) removeCanonicalCameraTrack(track, !wasPublished);
14582
+ else if (isMountedRef.current) setLocalMedia(function(current) {
14583
+ return _object_spread_props$b(_object_spread$d({}, current), {
14584
+ camera: false
14585
+ });
14586
+ });
14587
+ return [
14588
+ 2
14589
+ ];
14590
+ case 6:
14591
+ if (isMountedRef.current) setLocalMedia(function(current) {
14592
+ return _object_spread_props$b(_object_spread$d({}, current), {
14593
+ camera: true
14594
+ });
14595
+ });
14596
+ return [
14597
+ 3,
14598
+ 8
14599
+ ];
14600
+ case 7:
14601
+ publishError = _state.sent();
14602
+ latestAccess1 = accessRef.current;
14603
+ canRetain = isLifecycleActive(lifecycle) && latestAccess1 !== undefined && ((_roomConnectionRef_current2 = roomConnectionRef.current) === null || _roomConnectionRef_current2 === void 0 ? void 0 : _roomConnectionRef_current2.room) === currentRoom && cameraDesiredRef.current && canPreviewCamera(latestAccess1.capabilities) && cameraShouldCapture(currentRoom, latestAccess1);
14604
+ if (!canRetain) removeCanonicalCameraTrack(track, true);
14605
+ reportError(publishError, {
14606
+ recoverable: true,
14607
+ scope: 'media'
14608
+ });
14609
+ return [
14610
+ 3,
14611
+ 8
14612
+ ];
14613
+ case 8:
14614
+ return [
14615
+ 2
14616
+ ];
14617
+ }
14618
+ });
14619
+ })();
14620
+ }, [
14621
+ cameraShouldCapture,
14622
+ cameraShouldPublish,
14623
+ isLifecycleActive,
14624
+ removeCanonicalCameraTrack,
14625
+ reportError,
14626
+ unpublishCanonicalCamera
14627
+ ]);
14628
+ var handleCameraEnded = useCallback(function(lifecycle, endedTrack) {
14629
+ return _async_to_generator$k(function() {
14630
+ var _roomConnectionRef_current, _roomConnectionRef_current1, currentRoom, currentAccess, publication, revision, generation, _roomConnectionRef_current2, latestAccess, canKeepRestartedTrack, latestAccess1;
14631
+ return _ts_generator$k(this, function(_state) {
14632
+ switch(_state.label){
14633
+ case 0:
14634
+ if (canonicalCameraTrackRef.current !== endedTrack || !isLifecycleActive(lifecycle)) return [
14635
+ 2
14636
+ ];
14637
+ currentRoom = (_roomConnectionRef_current = roomConnectionRef.current) === null || _roomConnectionRef_current === void 0 ? void 0 : _roomConnectionRef_current.room;
14638
+ currentAccess = accessRef.current;
14639
+ if (!currentRoom || !currentAccess) return [
14640
+ 2
14641
+ ];
14642
+ publication = currentRoom.localParticipant.getTrackPublication(Track.Source.Camera);
14643
+ if ((publication === null || publication === void 0 ? void 0 : publication.track) === endedTrack) return [
14644
+ 2
14645
+ ];
14646
+ revision = cameraRevisionRef.current;
14647
+ generation = accessGenerationRef.current;
14648
+ if (!cameraShouldCapture(currentRoom, currentAccess)) {
14649
+ removeCanonicalCameraTrack(endedTrack, true);
14650
+ return [
14651
+ 2
14652
+ ];
14653
+ }
14654
+ _state.label = 1;
14655
+ case 1:
14656
+ _state.trys.push([
14657
+ 1,
14658
+ 3,
14659
+ ,
14660
+ 4
14661
+ ]);
14662
+ return [
14663
+ 4,
14664
+ endedTrack.restartTrack()
14665
+ ];
14666
+ case 2:
14667
+ _state.sent();
14668
+ latestAccess = accessRef.current;
14669
+ canKeepRestartedTrack = canonicalCameraTrackRef.current === endedTrack && isLifecycleActive(lifecycle) && cameraRevisionRef.current === revision && accessGenerationRef.current === generation && ((_roomConnectionRef_current2 = roomConnectionRef.current) === null || _roomConnectionRef_current2 === void 0 ? void 0 : _roomConnectionRef_current2.room) === currentRoom && latestAccess !== undefined && cameraShouldCapture(currentRoom, latestAccess);
14670
+ if (canKeepRestartedTrack && isMountedRef.current) setLocalCameraTrack(endedTrack);
14671
+ else if (canonicalCameraTrackRef.current === endedTrack) removeCanonicalCameraTrack(endedTrack, true);
14672
+ return [
14673
+ 2
14674
+ ];
14675
+ case 3:
14676
+ _state.sent();
14677
+ return [
14678
+ 3,
14679
+ 4
14680
+ ];
14681
+ case 4:
14682
+ latestAccess1 = accessRef.current;
14683
+ if (!(canonicalCameraTrackRef.current === endedTrack && isLifecycleActive(lifecycle) && cameraRevisionRef.current === revision && accessGenerationRef.current === generation && ((_roomConnectionRef_current1 = roomConnectionRef.current) === null || _roomConnectionRef_current1 === void 0 ? void 0 : _roomConnectionRef_current1.room) === currentRoom && latestAccess1 !== undefined && cameraShouldCapture(currentRoom, latestAccess1))) return [
14684
+ 3,
14685
+ 6
14686
+ ];
14687
+ removeCanonicalCameraTrack(endedTrack, true);
14688
+ return [
14689
+ 4,
14690
+ ensureLocalCameraTrack(lifecycle, revision, generation, currentRoom)
14691
+ ];
14692
+ case 5:
14693
+ _state.sent();
14694
+ return [
14695
+ 3,
14696
+ 7
14697
+ ];
14698
+ case 6:
14699
+ if (canonicalCameraTrackRef.current === endedTrack) removeCanonicalCameraTrack(endedTrack, true);
14700
+ _state.label = 7;
14701
+ case 7:
14702
+ return [
14703
+ 2
14704
+ ];
14705
+ }
14706
+ });
14707
+ })();
14708
+ }, [
14709
+ cameraShouldCapture,
14710
+ ensureLocalCameraTrack,
14711
+ isLifecycleActive,
14712
+ removeCanonicalCameraTrack
14713
+ ]);
14714
+ useEffect(function() {
14715
+ handleCameraEndedRef.current = handleCameraEnded;
14716
+ }, [
14717
+ handleCameraEnded
14718
+ ]);
14719
+ var reconcileCanonicalCamera = useCallback(function() {
14720
+ var lifecycle = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : lifecycleRef.current, revision = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : cameraRevisionRef.current, generation = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : accessGenerationRef.current;
14721
+ if (!lifecycle) return Promise.resolve();
14722
+ return enqueueCameraTransition(function() {
14723
+ return _async_to_generator$k(function() {
14724
+ var _canonicalCameraTrackRef_current, connection, currentAccess, shouldCapture, track, _tmp;
14725
+ return _ts_generator$k(this, function(_state) {
14726
+ switch(_state.label){
14727
+ case 0:
14728
+ connection = roomConnectionRef.current;
14729
+ currentAccess = accessRef.current;
14730
+ if (!connection || connection.disposed || !currentAccess || cameraRevisionRef.current !== revision || accessGenerationRef.current !== generation) return [
14731
+ 2
14732
+ ];
14733
+ shouldCapture = cameraShouldCapture(connection.room, currentAccess);
14734
+ if (!!shouldCapture) return [
14735
+ 3,
14736
+ 2
14737
+ ];
14738
+ return [
14739
+ 4,
14740
+ unpublishCanonicalCamera(false)
14741
+ ];
14742
+ case 1:
14743
+ _state.sent();
14744
+ return [
14745
+ 2
14746
+ ];
14747
+ case 2:
14748
+ if (!((_canonicalCameraTrackRef_current = canonicalCameraTrackRef.current) !== null && _canonicalCameraTrackRef_current !== void 0)) return [
14749
+ 3,
14750
+ 3
14751
+ ];
14752
+ _tmp = _canonicalCameraTrackRef_current;
14753
+ return [
14754
+ 3,
14755
+ 5
14756
+ ];
14757
+ case 3:
14758
+ return [
14759
+ 4,
14760
+ ensureLocalCameraTrack(lifecycle, revision, generation, connection.room)
14761
+ ];
14762
+ case 4:
14763
+ _tmp = _state.sent();
14764
+ _state.label = 5;
14765
+ case 5:
14766
+ track = _tmp;
14767
+ if (!track) return [
14768
+ 2
14769
+ ];
14770
+ if (!cameraShouldPublish(connection.room, currentAccess)) return [
14771
+ 3,
14772
+ 7
14773
+ ];
14774
+ return [
14775
+ 4,
14776
+ publishCanonicalCamera(lifecycle, revision, generation, connection.room)
14777
+ ];
14778
+ case 6:
14779
+ _state.sent();
14780
+ return [
14781
+ 3,
14782
+ 9
14783
+ ];
14784
+ case 7:
14785
+ return [
14786
+ 4,
14787
+ unpublishCanonicalCamera(true)
14788
+ ];
14789
+ case 8:
14790
+ _state.sent();
14791
+ _state.label = 9;
14792
+ case 9:
14793
+ return [
14794
+ 2
14795
+ ];
14796
+ }
14797
+ });
14798
+ })();
14799
+ });
14800
+ }, [
14801
+ cameraShouldCapture,
14802
+ cameraShouldPublish,
14803
+ enqueueCameraTransition,
14804
+ ensureLocalCameraTrack,
14805
+ publishCanonicalCamera,
14806
+ unpublishCanonicalCamera
14807
+ ]);
14307
14808
  var disposeRoom = useCallback(function(connection) {
14308
14809
  var reconnectCompleted = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
14309
14810
  if (!connection.disposed) {
@@ -14395,7 +14896,7 @@ function RoomPlatformProvider(param) {
14395
14896
  ]);
14396
14897
  var connectLiveKit = useCallback(function(nextAccess, lifecycle) {
14397
14898
  return _async_to_generator$k(function() {
14398
- var _nextAccess_integrations, existingConnection, mediaState, createdConnection, nextRoom, connection, connection1, connectError, restorationResults, initialMediaResults, shouldCreateLocalPreview, previewTrack, previewError;
14899
+ var _nextAccess_integrations, existingConnection, mediaState, createdConnection, nextRoom, connection, connection1, connectError, firstSuccessfulConnection, restorationResults, initialMediaResults;
14399
14900
  return _ts_generator$k(this, function(_state) {
14400
14901
  switch(_state.label){
14401
14902
  case 0:
@@ -14435,8 +14936,47 @@ function RoomPlatformProvider(param) {
14435
14936
  connection.reconnecting = false;
14436
14937
  reportLifecycleEvent('reconnect.succeeded');
14437
14938
  }
14438
- void syncControlState();
14439
- if (isMountedRef.current && !connection.disposed) setStatus('connected');
14939
+ var _$lifecycle = lifecycleRef.current;
14940
+ var generation = accessGenerationRef.current;
14941
+ void function() {
14942
+ return _async_to_generator$k(function() {
14943
+ var _tmp;
14944
+ return _ts_generator$k(this, function(_state) {
14945
+ switch(_state.label){
14946
+ case 0:
14947
+ _tmp = !_$lifecycle;
14948
+ if (_tmp) return [
14949
+ 3,
14950
+ 2
14951
+ ];
14952
+ return [
14953
+ 4,
14954
+ syncControlState()
14955
+ ];
14956
+ case 1:
14957
+ _tmp = !_state.sent();
14958
+ _state.label = 2;
14959
+ case 2:
14960
+ if (_tmp) return [
14961
+ 2
14962
+ ];
14963
+ if (generation !== accessGenerationRef.current || connection.disposed) return [
14964
+ 2
14965
+ ];
14966
+ return [
14967
+ 4,
14968
+ reconcileCanonicalCamera(_$lifecycle, cameraRevisionRef.current, generation)
14969
+ ];
14970
+ case 3:
14971
+ _state.sent();
14972
+ if (isMountedRef.current && !connection.disposed) setStatus('connected');
14973
+ return [
14974
+ 2
14975
+ ];
14976
+ }
14977
+ });
14978
+ })();
14979
+ }();
14440
14980
  },
14441
14981
  disconnected: function() {
14442
14982
  for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
@@ -14493,7 +15033,7 @@ function RoomPlatformProvider(param) {
14493
15033
  },
14494
15034
  localMediaChanged: function() {
14495
15035
  if (isMountedRef.current && !connection.disposed) {
14496
- setLocalCameraTrack(localCameraTrackOf(connection.room));
15036
+ setLocalCameraTrack(canonicalCameraTrackRef.current);
14497
15037
  setLocalMedia(localMediaStateOf(connection.room));
14498
15038
  }
14499
15039
  },
@@ -14569,7 +15109,13 @@ function RoomPlatformProvider(param) {
14569
15109
  2
14570
15110
  ];
14571
15111
  }
14572
- if (!(hasFirstSuccessfulConnectionRef.current && mediaState)) return [
15112
+ firstSuccessfulConnection = !hasFirstSuccessfulConnectionRef.current;
15113
+ accessRef.current = nextAccess;
15114
+ accessGenerationRef.current += 1;
15115
+ if (firstSuccessfulConnection) cameraDesiredRef.current = nextAccess.capabilities.includes(localMediaCapabilities.camera) || nextAccess.capabilities.includes('room:speak_request');
15116
+ setIntegrations((_nextAccess_integrations = nextAccess.integrations) !== null && _nextAccess_integrations !== void 0 ? _nextAccess_integrations : null);
15117
+ setAccess(nextAccess);
15118
+ if (!(!firstSuccessfulConnection && mediaState)) return [
14573
15119
  3,
14574
15120
  6
14575
15121
  ];
@@ -14577,7 +15123,6 @@ function RoomPlatformProvider(param) {
14577
15123
  4,
14578
15124
  Promise.allSettled([
14579
15125
  connection1.room.localParticipant.setMicrophoneEnabled(mediaState.microphone),
14580
- connection1.room.localParticipant.setCameraEnabled(mediaState.camera),
14581
15126
  connection1.room.localParticipant.setScreenShareEnabled(mediaState.screenShare)
14582
15127
  ])
14583
15128
  ];
@@ -14597,8 +15142,7 @@ function RoomPlatformProvider(param) {
14597
15142
  return [
14598
15143
  4,
14599
15144
  Promise.allSettled([
14600
- connection1.room.localParticipant.setMicrophoneEnabled(nextAccess.capabilities.includes(localMediaCapabilities.microphone)),
14601
- connection1.room.localParticipant.setCameraEnabled(nextAccess.capabilities.includes(localMediaCapabilities.camera))
15145
+ connection1.room.localParticipant.setMicrophoneEnabled(nextAccess.capabilities.includes(localMediaCapabilities.microphone))
14602
15146
  ])
14603
15147
  ];
14604
15148
  case 7:
@@ -14617,58 +15161,23 @@ function RoomPlatformProvider(param) {
14617
15161
  2
14618
15162
  ];
14619
15163
  }
14620
- shouldCreateLocalPreview = !hasFirstSuccessfulConnectionRef.current && !localPreviewTrackRef.current && nextAccess.capabilities.includes('room:speak_request') && !nextAccess.capabilities.includes(localMediaCapabilities.camera);
14621
- if (!shouldCreateLocalPreview) return [
14622
- 3,
14623
- 12
15164
+ hasFirstSuccessfulConnectionRef.current = true;
15165
+ setActiveDevices(activeDevicesStateOf(connection1.room));
15166
+ setLocalCameraTrack(canonicalCameraTrackRef.current);
15167
+ setLocalMedia(mediaState !== null && mediaState !== void 0 ? mediaState : localMediaStateOf(connection1.room));
15168
+ return [
15169
+ 4,
15170
+ syncControlState()
14624
15171
  ];
14625
- _state.label = 9;
14626
15172
  case 9:
14627
- _state.trys.push([
14628
- 9,
14629
- 11,
14630
- ,
14631
- 12
14632
- ]);
15173
+ _state.sent();
14633
15174
  return [
14634
15175
  4,
14635
- createLocalVideoTrack()
15176
+ reconcileCanonicalCamera(lifecycle, cameraRevisionRef.current, accessGenerationRef.current)
14636
15177
  ];
14637
15178
  case 10:
14638
- previewTrack = _state.sent();
14639
- if (!isLifecycleActive(lifecycle) || connection1.disposed) {
14640
- previewTrack.stop();
14641
- disposeRoom(connection1, true);
14642
- return [
14643
- 2
14644
- ];
14645
- }
14646
- localPreviewTrackRef.current = previewTrack;
14647
- setLocalPreviewTrack(previewTrack);
14648
- return [
14649
- 3,
14650
- 12
14651
- ];
14652
- case 11:
14653
- previewError = _state.sent();
14654
- reportError(previewError, {
14655
- recoverable: true,
14656
- scope: 'media'
14657
- });
14658
- return [
14659
- 3,
14660
- 12
14661
- ];
14662
- case 12:
14663
- accessRef.current = nextAccess;
14664
- hasFirstSuccessfulConnectionRef.current = true;
14665
- setIntegrations((_nextAccess_integrations = nextAccess.integrations) !== null && _nextAccess_integrations !== void 0 ? _nextAccess_integrations : null);
14666
- setAccess(nextAccess);
14667
- setActiveDevices(activeDevicesStateOf(connection1.room));
14668
- setLocalCameraTrack(localCameraTrackOf(connection1.room));
14669
- setLocalMedia(mediaState !== null && mediaState !== void 0 ? mediaState : localMediaStateOf(connection1.room));
15179
+ _state.sent();
14670
15180
  setStatus('connected');
14671
- void syncControlState();
14672
15181
  return [
14673
15182
  2
14674
15183
  ];
@@ -14679,6 +15188,7 @@ function RoomPlatformProvider(param) {
14679
15188
  applyControlState,
14680
15189
  disposeRoom,
14681
15190
  isLifecycleActive,
15191
+ reconcileCanonicalCamera,
14682
15192
  reportError,
14683
15193
  reportLifecycleEvent,
14684
15194
  syncControlState
@@ -14842,7 +15352,6 @@ function RoomPlatformProvider(param) {
14842
15352
  errorScopeRef.current = undefined;
14843
15353
  setError(undefined);
14844
15354
  setLocalCameraTrack(null);
14845
- setLocalPreviewTrack(null);
14846
15355
  setLocalMedia(emptyLocalMediaState);
14847
15356
  setPrivateRoom(undefined);
14848
15357
  setPrivateRoomConnection(undefined);
@@ -14915,17 +15424,20 @@ function RoomPlatformProvider(param) {
14915
15424
  })();
14916
15425
  }();
14917
15426
  return function() {
14918
- var _localPreviewTrackRef_current;
14919
15427
  if (lifecycleRef.current === lifecycle) lifecycleRef.current = undefined;
14920
15428
  isMountedRef.current = false;
14921
15429
  recoveryRef.current = undefined;
14922
15430
  var connection = roomConnectionRef.current;
14923
15431
  if (connection) disposeRoom(connection);
14924
- (_localPreviewTrackRef_current = localPreviewTrackRef.current) === null || _localPreviewTrackRef_current === void 0 ? void 0 : _localPreviewTrackRef_current.stop();
14925
- localPreviewTrackRef.current = null;
15432
+ cameraRevisionRef.current += 1;
15433
+ var canonicalTrack = canonicalCameraTrackRef.current;
15434
+ if (canonicalTrack) removeCanonicalCameraTrack(canonicalTrack, true);
15435
+ cameraCreationRef.current = undefined;
15436
+ cameraTransitionRef.current = Promise.resolve();
14926
15437
  pendingActions.clear();
14927
15438
  pendingLocalMedia.clear();
14928
15439
  accessRef.current = undefined;
15440
+ accessGenerationRef.current += 1;
14929
15441
  controlStateRef.current = undefined;
14930
15442
  controlStateSyncRef.current = undefined;
14931
15443
  setPrivateRoom(undefined);
@@ -14937,6 +15449,7 @@ function RoomPlatformProvider(param) {
14937
15449
  disposeRoom,
14938
15450
  isLifecycleActive,
14939
15451
  recover,
15452
+ removeCanonicalCameraTrack,
14940
15453
  reportError
14941
15454
  ]);
14942
15455
  var hasCapability = useCallback(function(capability) {
@@ -15070,25 +15583,43 @@ function RoomPlatformProvider(param) {
15070
15583
  reportError
15071
15584
  ]);
15072
15585
  var setLocalMediaEnabled = useCallback(function(kind, enabled) {
15073
- var existingOperation = pendingLocalMediaRef.current.get(kind);
15586
+ var existingOperation = kind === 'camera' ? undefined : pendingLocalMediaRef.current.get(kind);
15074
15587
  if (existingOperation !== undefined) return existingOperation;
15075
15588
  var operation = (function() {
15076
15589
  return _async_to_generator$k(function() {
15077
- var _controlStateRef_current, _accessRef_current, hasTemporarySpeakerGrant, connection, ringingPrivateRoom, participant, actorId, isRingingForActor, _ref, currentSnapshot, snapshot;
15590
+ var _controlStateRef_current, _accessRef_current, connection, currentAccess, hasTemporarySpeakerGrant, ringingPrivateRoom, participant, actorId, isRingingForActor, _ref, currentSnapshot, snapshot;
15078
15591
  return _ts_generator$k(this, function(_state) {
15079
15592
  switch(_state.label){
15080
15593
  case 0:
15594
+ connection = roomConnectionRef.current;
15595
+ if (!(kind === 'camera')) return [
15596
+ 3,
15597
+ 2
15598
+ ];
15599
+ cameraDesiredRef.current = enabled;
15600
+ cameraRevisionRef.current += 1;
15601
+ if (!connection || connection.disposed) throw new Error('ROOM_PLATFORM_ROOM_UNAVAILABLE');
15602
+ currentAccess = accessRef.current;
15603
+ if (enabled && currentAccess && !canPreviewCamera(currentAccess.capabilities) && !cameraShouldBeForced(connection.room)) {
15604
+ cameraDesiredRef.current = false;
15605
+ throw new Error('ROOM_PLATFORM_MEDIA_CAPABILITY_DENIED');
15606
+ }
15607
+ return [
15608
+ 4,
15609
+ reconcileCanonicalCamera(lifecycleRef.current, cameraRevisionRef.current, accessGenerationRef.current)
15610
+ ];
15611
+ case 1:
15612
+ _state.sent();
15613
+ clearMediaError();
15614
+ return [
15615
+ 2
15616
+ ];
15617
+ case 2:
15081
15618
  hasTemporarySpeakerGrant = kind !== 'screenShare' && ((_controlStateRef_current = controlStateRef.current) === null || _controlStateRef_current === void 0 ? void 0 : _controlStateRef_current.activeSpeakerParticipantIdentity) === ((_accessRef_current = accessRef.current) === null || _accessRef_current === void 0 ? void 0 : _accessRef_current.liveKit.participantIdentity);
15082
15619
  if (!hasCapability(localMediaCapabilities[kind]) && !hasTemporarySpeakerGrant) throw new Error('ROOM_PLATFORM_MEDIA_CAPABILITY_DENIED');
15083
- connection = roomConnectionRef.current;
15084
15620
  if (!connection || connection.disposed) throw new Error('ROOM_PLATFORM_ROOM_UNAVAILABLE');
15085
15621
  switch(kind){
15086
15622
  case 'microphone':
15087
- return [
15088
- 3,
15089
- 1
15090
- ];
15091
- case 'camera':
15092
15623
  return [
15093
15624
  3,
15094
15625
  3
@@ -15103,21 +15634,10 @@ function RoomPlatformProvider(param) {
15103
15634
  3,
15104
15635
  7
15105
15636
  ];
15106
- case 1:
15107
- return [
15108
- 4,
15109
- connection.room.localParticipant.setMicrophoneEnabled(enabled)
15110
- ];
15111
- case 2:
15112
- _state.sent();
15113
- return [
15114
- 3,
15115
- 7
15116
- ];
15117
15637
  case 3:
15118
15638
  return [
15119
15639
  4,
15120
- connection.room.localParticipant.setCameraEnabled(enabled)
15640
+ connection.room.localParticipant.setMicrophoneEnabled(enabled)
15121
15641
  ];
15122
15642
  case 4:
15123
15643
  _state.sent();
@@ -15141,16 +15661,17 @@ function RoomPlatformProvider(param) {
15141
15661
  participant = connection.room.localParticipant;
15142
15662
  actorId = externalActorIdFromMetadata$2(participant.metadata);
15143
15663
  isRingingForActor = Boolean((ringingPrivateRoom === null || ringingPrivateRoom === void 0 ? void 0 : ringingPrivateRoom.status) === 'ringing' && actorId && (ringingPrivateRoom.callerExternalActorId === actorId || ringingPrivateRoom.studentExternalActorId === actorId));
15144
- if (isRingingForActor && (kind === 'microphone' || kind === 'camera')) {
15664
+ if (isRingingForActor && kind === 'microphone') {
15145
15665
  currentSnapshot = privateMediaSnapshotRef.current;
15146
15666
  snapshot = (currentSnapshot === null || currentSnapshot === void 0 ? void 0 : currentSnapshot.room) === connection.room && currentSnapshot.privateRoomId === (ringingPrivateRoom === null || ringingPrivateRoom === void 0 ? void 0 : ringingPrivateRoom.id) ? currentSnapshot : {
15147
- cameraEnabled: participant.isCameraEnabled,
15148
15667
  microphoneEnabled: participant.isMicrophoneEnabled,
15149
15668
  privateRoomId: (_ref = ringingPrivateRoom === null || ringingPrivateRoom === void 0 ? void 0 : ringingPrivateRoom.id) !== null && _ref !== void 0 ? _ref : '',
15150
15669
  room: connection.room,
15151
15670
  suppressed: false
15152
15671
  };
15153
- privateMediaSnapshotRef.current = _object_spread_props$b(_object_spread$d({}, snapshot), _define_property$f({}, kind === 'camera' ? 'cameraEnabled' : 'microphoneEnabled', enabled));
15672
+ privateMediaSnapshotRef.current = _object_spread_props$b(_object_spread$d({}, snapshot), {
15673
+ microphoneEnabled: enabled
15674
+ });
15154
15675
  }
15155
15676
  clearMediaError();
15156
15677
  if (isMountedRef.current && !connection.disposed) setLocalMedia(function(current) {
@@ -15168,25 +15689,27 @@ function RoomPlatformProvider(param) {
15168
15689
  scope: 'media'
15169
15690
  });
15170
15691
  throw mediaError;
15171
- }).finally(function() {
15692
+ });
15693
+ if (kind === 'camera') return operation;
15694
+ var trackedOperation = operation.finally(function() {
15172
15695
  pendingLocalMediaRef.current.delete(kind);
15173
15696
  if (isMountedRef.current) setPendingLocalMediaKinds(_to_consumable_array$7(pendingLocalMediaRef.current.keys()));
15174
15697
  });
15175
- pendingLocalMediaRef.current.set(kind, operation);
15698
+ pendingLocalMediaRef.current.set(kind, trackedOperation);
15176
15699
  if (isMountedRef.current) setPendingLocalMediaKinds(_to_consumable_array$7(pendingLocalMediaRef.current.keys()));
15177
- return operation;
15700
+ return trackedOperation;
15178
15701
  }, [
15702
+ cameraShouldBeForced,
15179
15703
  clearMediaError,
15180
15704
  hasCapability,
15705
+ reconcileCanonicalCamera,
15181
15706
  reportError
15182
15707
  ]);
15183
15708
  var currentExternalActorId = externalActorIdFromMetadata$2(room === null || room === void 0 ? void 0 : room.localParticipant.metadata);
15184
15709
  var privateRoomForActor = Boolean(privateRoom && currentExternalActorId && (privateRoom.callerExternalActorId === currentExternalActorId || privateRoom.studentExternalActorId === currentExternalActorId));
15185
15710
  var privateRoomActiveForActor = privateRoomForActor && (privateRoom === null || privateRoom === void 0 ? void 0 : privateRoom.status) === 'active';
15186
15711
  var localParticipantIsActiveSpeaker = Boolean(access && (controlState === null || controlState === void 0 ? void 0 : controlState.activeSpeakerParticipantIdentity) === access.liveKit.participantIdentity);
15187
- var localParticipantMonitorCamera = (controlState === null || controlState === void 0 ? void 0 : controlState.monitorActive) === true && roleFromMetadata(room === null || room === void 0 ? void 0 : room.localParticipant.metadata) === 'student';
15188
15712
  var canPublishAudioNow = !privateRoomActiveForActor && (hasCapability(localMediaCapabilities.microphone) || localParticipantIsActiveSpeaker);
15189
- var canPublishCameraNow = !privateRoomActiveForActor && (hasCapability(localMediaCapabilities.camera) || localParticipantIsActiveSpeaker || localParticipantMonitorCamera);
15190
15713
  var canPublishScreenShareNow = hasCapability(localMediaCapabilities.screenShare) && ((_ref = controlState === null || controlState === void 0 ? void 0 : controlState.mode) !== null && _ref !== void 0 ? _ref : 'live') === 'live';
15191
15714
  useEffect(function() {
15192
15715
  if (!room || !privateRoomForActor || (privateRoom === null || privateRoom === void 0 ? void 0 : privateRoom.status) !== 'ringing') return;
@@ -15194,7 +15717,6 @@ function RoomPlatformProvider(param) {
15194
15717
  var snapshot = privateMediaSnapshotRef.current;
15195
15718
  if (!snapshot || snapshot.room !== room || snapshot.privateRoomId !== privateRoom.id) {
15196
15719
  privateMediaSnapshotRef.current = {
15197
- cameraEnabled: participant.isCameraEnabled,
15198
15720
  microphoneEnabled: participant.isMicrophoneEnabled,
15199
15721
  privateRoomId: privateRoom.id,
15200
15722
  room: room,
@@ -15212,7 +15734,6 @@ function RoomPlatformProvider(param) {
15212
15734
  var snapshot = privateMediaSnapshotRef.current;
15213
15735
  if (privateRoomActiveForActor && privateRoom) {
15214
15736
  privateMediaSnapshotRef.current = !snapshot || snapshot.room !== room || snapshot.privateRoomId !== privateRoom.id ? {
15215
- cameraEnabled: participant.isCameraEnabled,
15216
15737
  microphoneEnabled: participant.isMicrophoneEnabled,
15217
15738
  privateRoomId: privateRoom.id,
15218
15739
  room: room,
@@ -15222,9 +15743,9 @@ function RoomPlatformProvider(param) {
15222
15743
  });
15223
15744
  void Promise.allSettled([
15224
15745
  participant.setMicrophoneEnabled(false),
15225
- participant.setCameraEnabled(false),
15226
15746
  participant.setScreenShareEnabled(false)
15227
15747
  ]);
15748
+ void reconcileCanonicalCamera();
15228
15749
  return;
15229
15750
  }
15230
15751
  if (!snapshot) return;
@@ -15249,8 +15770,8 @@ function RoomPlatformProvider(param) {
15249
15770
  _state.trys.push([
15250
15771
  0,
15251
15772
  ,
15252
- 3,
15253
- 4
15773
+ 4,
15774
+ 5
15254
15775
  ]);
15255
15776
  return [
15256
15777
  4,
@@ -15272,8 +15793,7 @@ function RoomPlatformProvider(param) {
15272
15793
  return [
15273
15794
  4,
15274
15795
  Promise.allSettled([
15275
- participant.setMicrophoneEnabled(snapshot.microphoneEnabled),
15276
- participant.setCameraEnabled(snapshot.cameraEnabled)
15796
+ participant.setMicrophoneEnabled(snapshot.microphoneEnabled)
15277
15797
  ])
15278
15798
  ];
15279
15799
  case 2:
@@ -15290,14 +15810,20 @@ function RoomPlatformProvider(param) {
15290
15810
  privateMediaSnapshotRef.current = null;
15291
15811
  }
15292
15812
  if (isMountedRef.current && !((_roomConnectionRef_current = roomConnectionRef.current) === null || _roomConnectionRef_current === void 0 ? void 0 : _roomConnectionRef_current.disposed)) {
15293
- setLocalCameraTrack(localCameraTrackOf(snapshot.room));
15813
+ setLocalCameraTrack(canonicalCameraTrackRef.current);
15294
15814
  setLocalMedia(localMediaStateOf(snapshot.room));
15295
15815
  }
15296
15816
  return [
15297
- 3,
15298
- 4
15817
+ 4,
15818
+ reconcileCanonicalCamera()
15299
15819
  ];
15300
15820
  case 3:
15821
+ _state.sent();
15822
+ return [
15823
+ 3,
15824
+ 5
15825
+ ];
15826
+ case 4:
15301
15827
  if (privateMediaRestoreTaskRef.current === snapshot) {
15302
15828
  privateMediaRestoreTaskRef.current = null;
15303
15829
  if (isMountedRef.current) setPrivateMediaRestorePending(false);
@@ -15305,7 +15831,7 @@ function RoomPlatformProvider(param) {
15305
15831
  return [
15306
15832
  7
15307
15833
  ];
15308
- case 4:
15834
+ case 5:
15309
15835
  return [
15310
15836
  2
15311
15837
  ];
@@ -15317,6 +15843,7 @@ function RoomPlatformProvider(param) {
15317
15843
  privateRoom,
15318
15844
  privateRoomActiveForActor,
15319
15845
  privateRoomForActor,
15846
+ reconcileCanonicalCamera,
15320
15847
  reportError,
15321
15848
  room,
15322
15849
  syncControlState
@@ -15326,9 +15853,9 @@ function RoomPlatformProvider(param) {
15326
15853
  if (privateMediaRestorePending || privateMediaRestoreTaskRef.current !== null) return;
15327
15854
  var updates = [
15328
15855
  room.localParticipant.isMicrophoneEnabled === canPublishAudioNow ? undefined : room.localParticipant.setMicrophoneEnabled(canPublishAudioNow),
15329
- room.localParticipant.isCameraEnabled === canPublishCameraNow ? undefined : room.localParticipant.setCameraEnabled(canPublishCameraNow),
15330
15856
  (!canPublishScreenShareNow || privateRoomActiveForActor) && room.localParticipant.isScreenShareEnabled ? room.localParticipant.setScreenShareEnabled(false) : undefined
15331
15857
  ];
15858
+ void reconcileCanonicalCamera();
15332
15859
  if (!updates.some(Boolean)) return;
15333
15860
  void Promise.allSettled(updates).then(function(results) {
15334
15861
  var _roomConnectionRef_current;
@@ -15339,22 +15866,23 @@ function RoomPlatformProvider(param) {
15339
15866
  });
15340
15867
  });
15341
15868
  if (isMountedRef.current && !((_roomConnectionRef_current = roomConnectionRef.current) === null || _roomConnectionRef_current === void 0 ? void 0 : _roomConnectionRef_current.disposed)) {
15342
- setLocalCameraTrack(localCameraTrackOf(room));
15869
+ setLocalCameraTrack(canonicalCameraTrackRef.current);
15343
15870
  setLocalMedia(localMediaStateOf(room));
15344
15871
  }
15345
15872
  });
15346
15873
  }, [
15347
15874
  canPublishAudioNow,
15348
- canPublishCameraNow,
15349
15875
  canPublishScreenShareNow,
15876
+ controlState,
15350
15877
  privateMediaRestorePending,
15351
15878
  privateRoomActiveForActor,
15879
+ reconcileCanonicalCamera,
15352
15880
  reportError,
15353
15881
  room
15354
15882
  ]);
15355
15883
  var switchActiveDevice = useCallback(function(kind, deviceId) {
15356
15884
  return _async_to_generator$k(function() {
15357
- var connection, switched, deviceError;
15885
+ var connection, lifecycle, revision, generation, deviceError;
15358
15886
  return _ts_generator$k(this, function(_state) {
15359
15887
  switch(_state.label){
15360
15888
  case 0:
@@ -15368,13 +15896,56 @@ function RoomPlatformProvider(param) {
15368
15896
  ,
15369
15897
  4
15370
15898
  ]);
15899
+ lifecycle = lifecycleRef.current;
15900
+ revision = cameraRevisionRef.current;
15901
+ generation = accessGenerationRef.current;
15371
15902
  return [
15372
15903
  4,
15373
- connection.room.switchActiveDevice(kind, deviceId)
15904
+ enqueueCameraTransition(function() {
15905
+ return _async_to_generator$k(function() {
15906
+ var switched, canonicalTrack, publication;
15907
+ return _ts_generator$k(this, function(_state) {
15908
+ switch(_state.label){
15909
+ case 0:
15910
+ return [
15911
+ 4,
15912
+ connection.room.switchActiveDevice(kind, deviceId)
15913
+ ];
15914
+ case 1:
15915
+ switched = _state.sent();
15916
+ if (!switched) throw new Error('ROOM_PLATFORM_DEVICE_SWITCH_FAILED');
15917
+ if (!lifecycle || !isLifecycleActive(lifecycle) || cameraRevisionRef.current !== revision || accessGenerationRef.current !== generation || connection !== roomConnectionRef.current) return [
15918
+ 2
15919
+ ];
15920
+ if (kind !== 'videoinput') return [
15921
+ 2
15922
+ ];
15923
+ canonicalTrack = canonicalCameraTrackRef.current;
15924
+ publication = connection.room.localParticipant.getTrackPublication(Track.Source.Camera);
15925
+ if (!canonicalTrack || (publication === null || publication === void 0 ? void 0 : publication.track) === canonicalTrack) return [
15926
+ 2
15927
+ ];
15928
+ return [
15929
+ 4,
15930
+ canonicalTrack.setDeviceId({
15931
+ exact: deviceId
15932
+ })
15933
+ ];
15934
+ case 2:
15935
+ _state.sent();
15936
+ if (!isLifecycleActive(lifecycle) || cameraRevisionRef.current !== revision || accessGenerationRef.current !== generation || connection !== roomConnectionRef.current) return [
15937
+ 2
15938
+ ];
15939
+ return [
15940
+ 2
15941
+ ];
15942
+ }
15943
+ });
15944
+ })();
15945
+ })
15374
15946
  ];
15375
15947
  case 2:
15376
- switched = _state.sent();
15377
- if (!switched) throw new Error('ROOM_PLATFORM_DEVICE_SWITCH_FAILED');
15948
+ _state.sent();
15378
15949
  clearMediaError();
15379
15950
  if (isMountedRef.current && !connection.disposed) {
15380
15951
  setActiveDevices(function(current) {
@@ -15401,6 +15972,8 @@ function RoomPlatformProvider(param) {
15401
15972
  })();
15402
15973
  }, [
15403
15974
  clearMediaError,
15975
+ enqueueCameraTransition,
15976
+ isLifecycleActive,
15404
15977
  reportError
15405
15978
  ]);
15406
15979
  var isActionPending = useCallback(function(name, payload) {
@@ -15427,7 +16000,6 @@ function RoomPlatformProvider(param) {
15427
16000
  isActionPending: isActionPending,
15428
16001
  isLocalMediaPending: isLocalMediaPending,
15429
16002
  localCameraTrack: localCameraTrack,
15430
- localPreviewTrack: localPreviewTrack,
15431
16003
  localMedia: localMedia,
15432
16004
  performAction: performAction,
15433
16005
  room: room,
@@ -15445,7 +16017,6 @@ function RoomPlatformProvider(param) {
15445
16017
  isActionPending,
15446
16018
  isLocalMediaPending,
15447
16019
  localCameraTrack,
15448
- localPreviewTrack,
15449
16020
  localMedia,
15450
16021
  performAction,
15451
16022
  room,
@@ -16593,7 +17164,7 @@ function RoomPlatformVideoTile(param) {
16593
17164
  ].filter(Boolean).join(' '),
16594
17165
  "data-kind": kind,
16595
17166
  "data-mirrored": String(isMirrored),
16596
- "data-state": trackRef ? 'available' : 'empty',
17167
+ "data-state": hasMedia ? 'available' : 'empty',
16597
17168
  "data-testid": "room-platform-video-tile-".concat(kind),
16598
17169
  role: "group",
16599
17170
  children: [
@@ -18650,15 +19221,16 @@ function RoomPlatformCurrentOperationStrip(param) {
18650
19221
  }
18651
19222
 
18652
19223
  function RoomPlatformLocalPreview(param) {
18653
- var trackRef = param.trackRef, localPreviewTrack = param.localPreviewTrack;
19224
+ var trackRef = param.trackRef, localTrack = param.localTrack;
19225
+ var useCanonicalTrack = localTrack !== undefined;
18654
19226
  return /*#__PURE__*/ jsx(RoomPlatformVideoTile, {
18655
19227
  className: "hidden md:block",
18656
19228
  kind: "preview",
18657
19229
  label: "Camera của bạn",
18658
- media: localPreviewTrack ? /*#__PURE__*/ jsx(LocalVideoPreview, {
18659
- track: localPreviewTrack
19230
+ media: localTrack ? /*#__PURE__*/ jsx(LocalVideoPreview, {
19231
+ track: localTrack
18660
19232
  }) : undefined,
18661
- trackRef: trackRef
19233
+ trackRef: useCanonicalTrack ? undefined : trackRef
18662
19234
  });
18663
19235
  }
18664
19236
  function LocalVideoPreview(param) {
@@ -28261,7 +28833,7 @@ var RoomPlatformWorkspaceContent = function(param) {
28261
28833
  var cameraBackground = param.cameraBackground, completionAction = param.completionAction, extensions = param.extensions, modeConfig = param.modeConfig, onExit = param.onExit, sizing = param.sizing, stageModel = param.stageModel;
28262
28834
  var _resolvedStageModel_cameraOverlay, _ref, _ref1, _ref2, _ref3, _ref4;
28263
28835
  var _resolvedStageModel_primary, _resolvedStageModel_primary1, _extensions_sidebarTabs;
28264
- var _useRoomPlatform = useRoomPlatform(), access = _useRoomPlatform.access, controlState = _useRoomPlatform.controlState, error = _useRoomPlatform.error, hasCapability = _useRoomPlatform.hasCapability, isActionPending = _useRoomPlatform.isActionPending, localPreviewTrack = _useRoomPlatform.localPreviewTrack, performAction = _useRoomPlatform.performAction, status = _useRoomPlatform.status;
28836
+ var _useRoomPlatform = useRoomPlatform(), access = _useRoomPlatform.access, controlState = _useRoomPlatform.controlState, error = _useRoomPlatform.error, hasCapability = _useRoomPlatform.hasCapability, isActionPending = _useRoomPlatform.isActionPending, localCameraTrack = _useRoomPlatform.localCameraTrack, performAction = _useRoomPlatform.performAction, status = _useRoomPlatform.status;
28265
28837
  var integrations = useRoomPlatformIntegrations().integrations;
28266
28838
  var _useRoomPlatformPrivateRoom = useRoomPlatformPrivateRoom(), cancelPrivateRoom = _useRoomPlatformPrivateRoom.cancelPrivateRoom, currentPrivateRoomOperation = _useRoomPlatformPrivateRoom.currentPrivateRoomOperation;
28267
28839
  var resolvedStageModel = stageModel !== null && stageModel !== void 0 ? stageModel : emptyStageModel;
@@ -28503,7 +29075,7 @@ var RoomPlatformWorkspaceContent = function(param) {
28503
29075
  trackRef: resolvedStageModel.activeSpeaker
28504
29076
  }) : undefined;
28505
29077
  var localMediaSlot = (selectedHostCamera === null || selectedHostCamera === void 0 ? void 0 : selectedHostCamera.participant.isLocal) ? undefined : /*#__PURE__*/ jsx(RoomPlatformLocalPreview, {
28506
- localPreviewTrack: localPreviewTrack,
29078
+ localTrack: localCameraTrack,
28507
29079
  trackRef: resolvedStageModel.localPreview
28508
29080
  });
28509
29081
  var activeSpeakerMediaSlot = hasActiveSpeaker && !canModerate ? activeSpeakerSlot : undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naviedu/room-platform-react",
3
- "version": "0.0.35",
3
+ "version": "0.0.36",
4
4
  "type": "module",
5
5
  "main": "./index.esm.js",
6
6
  "module": "./index.esm.js",