export function reducer()

in apps/meeting/src/providers/VideoTileGridProvider/state.tsx [157:397]


export function reducer(state: State, { type, payload }: Action): State {
  const { gridState, attendeeStates, videoSourceState, priorityBasedPolicy } = state;

  switch (type) {
  case VideoTileGridAction.UpdateAttendeeStates: {
    const { roster } = payload;

    // Remove attendee that left the meeting
    for (const attendeeId in attendeeStates) {
      if (!isContentShare(attendeeId) && !(attendeeId in roster)) {
        delete attendeeStates[attendeeId];
      }
    }

    // Add attendee that joined the meeting
    for (const attendeeId in roster) {
      const name = roster[attendeeId]?.name || '';

      if (attendeeId in attendeeStates) {
        attendeeStates[attendeeId].name = name;
      } else {
        attendeeStates[attendeeId] = {
          attendeeId,
          name,
          videoEnabled: false,
          bandwidthConstrained: false,
        } as AttendeeState;
      }
    }

    // Ensure the state of `videoEnabled` in the racing condition of UpdateAttendeeStates and UpdateVideoSources
    for (const attendeeId of videoSourceState.cameraSources) {
      if (attendeeId in attendeeStates) {
        attendeeStates[attendeeId].videoEnabled = true;
      }
    }

    return {
      ...state,
      attendeeStates,
    };
  }

  case VideoTileGridAction.UpdateVideoSources: {
    const { videoSources, localAttendeeId } = payload as { videoSources: VideoSource[]; localAttendeeId: string | null };
    const cameraSources: string[] = [];
    const videoSourceIdSet = new Set(
      videoSources.map(videoSource => videoSource.attendee.attendeeId)
    );

    for (const attendeeId in attendeeStates) {
      // Reset the `videoEnabled` for all remote attendees
      if (!localAttendeeId || attendeeId !== localAttendeeId) {
        attendeeStates[attendeeId].videoEnabled = false;
      }

      // Remove content share from attendeeStates,
      // if content share is not in video sources
      if (
        isContentShare(attendeeId) &&
          !videoSourceIdSet.has(attendeeId)
      ) {
        delete attendeeStates[attendeeId];
      }
    }

    // Update the `videoEnabled` according to `videoSources`
    for (const attendeeId of videoSourceIdSet) {
      if (!(attendeeId in attendeeStates)) {
        if (isContentShare(attendeeId)) {
          attendeeStates[attendeeId] = {
            attendeeId,
            name: 'content share',
            bandwidthConstrained: false,
          } as AttendeeState;
        } else {
          attendeeStates[attendeeId] = {
            attendeeId,
            name: '',
            bandwidthConstrained: false,
          } as AttendeeState;
        }
      }

      attendeeStates[attendeeId].videoEnabled = true;
    }

    // Populate the `cameraSources` based on the order of `attendeeStates`
    for (const attendeeId in attendeeStates) {
      const attendee = attendeeStates[attendeeId];

      if (
        attendee.videoEnabled &&
          !isContentShare(attendee.attendeeId) &&
          attendee.attendeeId !== localAttendeeId
      ) {
        cameraSources.push(attendee.attendeeId);
      }
    }

    // Remove the attendee from `activeSpeakersWithCameraSource`,
    // if this attendee close the camera while still active
    for (const attendeeId in videoSourceState.activeSpeakersWithCameraSource) {
      if (!attendeeStates[attendeeId]?.videoEnabled) {
        videoSourceState.activeSpeakersWithCameraSource.filter(id => id !== attendeeId);
      }
    }

    videoSourceState.cameraSources = cameraSources;
    updateDownlinkPreferences(gridState, videoSourceState, attendeeStates, priorityBasedPolicy);

    return {
      ...state,
      attendeeStates,
      videoSourceState,
    };
  }

  case VideoTileGridAction.UpdateActiveSpeakers: {
    const { activeSpeakers } = payload;
    const activeSpeakersWithCameraSource = [];
    const { cameraSources } = videoSourceState;

    for (const attendeeId of activeSpeakers) {
      if (
        attendeeStates[attendeeId]?.videoEnabled &&
          cameraSources.includes(attendeeId)
      ) {
        activeSpeakersWithCameraSource.push(attendeeId);
      }
    }

    videoSourceState.activeSpeakersWithCameraSource = activeSpeakersWithCameraSource;
    updateDownlinkPreferences(gridState, videoSourceState, attendeeStates, priorityBasedPolicy);

    return {
      ...state,
      videoSourceState,
    };
  }

  case VideoTileGridAction.UpdateLocalSourceState: {
    const {
      isVideoEnabled,
      localAttendeeId,
      isLocalUserSharing,
      sharingAttendeeId,
    } = payload;

    videoSourceState.hasLocalVideo = isVideoEnabled;
    videoSourceState.hasLocalContentSharing = isLocalUserSharing;
    videoSourceState.contentShareId = sharingAttendeeId;

    if (localAttendeeId && localAttendeeId in attendeeStates) {
      attendeeStates[localAttendeeId].videoEnabled = isVideoEnabled;
    }

    updateDownlinkPreferences(gridState, videoSourceState, attendeeStates, priorityBasedPolicy);

    return {
      ...state,
      attendeeStates,
      videoSourceState,
    };
  }

  case VideoTileGridAction.UpdateLayout: {
    const { layout } = payload;
    gridState.layout = layout;
    updateDownlinkPreferences(gridState, videoSourceState, attendeeStates, priorityBasedPolicy);

    return {
      ...state,
      gridState,
    };
  }

  case VideoTileGridAction.PauseVideoTile: {
    const { attendeeId } = payload;
    if (attendeeId in attendeeStates) {
      attendeeStates[attendeeId].bandwidthConstrained = true;
    }

    return {
      ...state,
      attendeeStates,
    };
  }

  case VideoTileGridAction.UnpauseVideoTile: {
    const { attendeeId } = payload;
    if (attendeeId in attendeeStates) {
      attendeeStates[attendeeId].bandwidthConstrained = false;
    }

    return {
      ...state,
      attendeeStates,
    };
  }

  case VideoTileGridAction.ZoomIn: {
    const { threshold } = gridState;
    const { cameraSources, hasLocalVideo } = videoSourceState;
    const numberOfTiles = cameraSources.length + (hasLocalVideo ? 1 : 0);

    if (numberOfTiles > threshold) {
      gridState.isZoomed = true;
      updateDownlinkPreferences(gridState, videoSourceState, attendeeStates, priorityBasedPolicy);
    }

    return {
      ...state,
      gridState,
    };
  }

  case VideoTileGridAction.ZoomOut: {
    if (gridState.isZoomed) {
      gridState.isZoomed = false;
      updateDownlinkPreferences(gridState, videoSourceState, attendeeStates, priorityBasedPolicy);
    }

    return {
      ...state,
    };
  }

  case VideoTileGridAction.SetPriorityBasedPolicy: {
    const { policy } = payload as { policy: VideoPriorityBasedPolicy | undefined};

    return {
      ...state,
      ...{ priorityBasedPolicy: policy },
    };
  }

  default:
    throw new Error('Incorrect type in VideoTileGridProvider');
  }
}