You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // @ts-expect-error
  2. import VideoLayout from '../../../modules/UI/videolayout/VideoLayout';
  3. import { IStore } from '../app/types';
  4. import { MEDIA_TYPE } from '../base/media/constants';
  5. import { getTrackByMediaTypeAndParticipant } from '../base/tracks/functions.web';
  6. import { SET_SEE_WHAT_IS_BEING_SHARED } from './actionTypes';
  7. export * from './actions.any';
  8. /**
  9. * Captures a screenshot of the video displayed on the large video.
  10. *
  11. * @returns {Function}
  12. */
  13. export function captureLargeVideoScreenshot() {
  14. return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
  15. const state = getState();
  16. const largeVideo = state['features/large-video'];
  17. const promise = Promise.resolve();
  18. if (!largeVideo) {
  19. return promise;
  20. }
  21. const tracks = state['features/base/tracks'];
  22. const participantTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, largeVideo.participantId);
  23. // Participants that join the call video muted do not have a jitsiTrack attached.
  24. if (!participantTrack?.jitsiTrack) {
  25. return promise;
  26. }
  27. const videoStream = participantTrack.jitsiTrack.getOriginalStream();
  28. if (!videoStream) {
  29. return promise;
  30. }
  31. // Get the video element for the large video, cast HTMLElement to HTMLVideoElement to make flow happy.
  32. /* eslint-disable-next-line no-extra-parens*/
  33. const videoElement = (document.getElementById('largeVideo') as any);
  34. if (!videoElement) {
  35. return promise;
  36. }
  37. // Create a HTML canvas and draw video on to the canvas.
  38. const [ track ] = videoStream.getVideoTracks();
  39. const { height, width } = track.getSettings() ?? track.getConstraints();
  40. const canvasElement = document.createElement('canvas');
  41. const ctx = canvasElement.getContext('2d');
  42. canvasElement.style.display = 'none';
  43. canvasElement.height = parseInt(height, 10);
  44. canvasElement.width = parseInt(width, 10);
  45. ctx?.drawImage(videoElement, 0, 0);
  46. const dataURL = canvasElement.toDataURL('image/png', 1.0);
  47. // Cleanup.
  48. ctx?.clearRect(0, 0, canvasElement.width, canvasElement.height);
  49. canvasElement.remove();
  50. return Promise.resolve(dataURL);
  51. };
  52. }
  53. /**
  54. * Resizes the large video container based on the dimensions provided.
  55. *
  56. * @param {number} width - Width that needs to be applied on the large video container.
  57. * @param {number} height - Height that needs to be applied on the large video container.
  58. * @returns {Function}
  59. */
  60. export function resizeLargeVideo(width: number, height: number) {
  61. return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
  62. const state = getState();
  63. const largeVideo = state['features/large-video'];
  64. if (largeVideo) {
  65. const largeVideoContainer = VideoLayout.getLargeVideo();
  66. largeVideoContainer.updateContainerSize(width, height);
  67. largeVideoContainer.resize();
  68. }
  69. };
  70. }
  71. /**
  72. * Updates the value used to display what is being shared.
  73. *
  74. * @param {boolean} seeWhatIsBeingShared - The current value.
  75. * @returns {{
  76. * type: SET_SEE_WHAT_IS_BEING_SHARED,
  77. * seeWhatIsBeingShared: boolean
  78. * }}
  79. */
  80. export function setSeeWhatIsBeingShared(seeWhatIsBeingShared: boolean) {
  81. return {
  82. type: SET_SEE_WHAT_IS_BEING_SHARED,
  83. seeWhatIsBeingShared
  84. };
  85. }