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.

functions.any.ts 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import { IReduxState, IStore } from '../app/types';
  2. import { getLocalizedDateFormatter } from '../base/i18n/dateUtil';
  3. import {
  4. IconImage,
  5. IconShareDoc,
  6. IconVideo,
  7. IconVolumeUp
  8. } from '../base/icons/svg';
  9. import { MEET_FEATURES } from '../base/jwt/constants';
  10. import { isJwtFeatureEnabled } from '../base/jwt/functions';
  11. import { showErrorNotification } from '../notifications/actions';
  12. import { NOTIFICATION_TIMEOUT_TYPE, NOTIFICATION_TYPE } from '../notifications/constants';
  13. import { uploadFiles } from './actions';
  14. import { MAX_FILE_SIZE } from './constants';
  15. /**
  16. * Checks whether file sharing feature is enabled.
  17. *
  18. * @param {IReduxState} state - The redux state.
  19. * @returns {boolean} - Indicates if file sharing feature is enabled.
  20. */
  21. export function isFileSharingEnabled(state: IReduxState) {
  22. const { fileSharing } = state['features/base/config'] ?? {};
  23. return Boolean(fileSharing?.enabled && fileSharing?.apiUrl);
  24. }
  25. /**
  26. * Gets the file extension from a file name.
  27. *
  28. * @param {string} fileName - The name of the file to extract the extension from.
  29. * @returns {string} The file extension or an empty string if none exists.
  30. */
  31. export function getFileExtension(fileName: string): string {
  32. const parts = fileName.split('.');
  33. if (parts.length > 1) {
  34. return parts.pop()?.toLowerCase() || '';
  35. }
  36. return '';
  37. }
  38. /**
  39. * Gets the appropriate icon for a file based on its type.
  40. *
  41. * @param {string} fileType - The file type.
  42. * @returns {Function} The icon component to use.
  43. */
  44. export function getFileIcon(fileType: string) {
  45. if ([ 'mkv', 'mp4', 'mov', 'avi', 'webm' ].includes(fileType)) {
  46. return IconVideo;
  47. }
  48. if ([ 'mp3', 'wav', 'ogg' ].includes(fileType)) {
  49. return IconVolumeUp;
  50. }
  51. if ([ 'jpg', 'jpeg', 'png', 'gif' ].includes(fileType)) {
  52. return IconImage;
  53. }
  54. return IconShareDoc;
  55. }
  56. /**
  57. * Formats the file size into a human-readable string.
  58. *
  59. * @param {number} bytes - The size in bytes.
  60. * @returns {string} The formatted file size string.
  61. */
  62. export function formatFileSize(bytes: number): string {
  63. if (bytes <= 0) {
  64. return '0 Bytes';
  65. }
  66. const sizes = [ 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB' ];
  67. const i = Math.floor(Math.log(bytes) / Math.log(1024));
  68. const size = bytes / Math.pow(1024, i);
  69. // Check if size is an integer after rounding to 2 decimals
  70. const rounded = Math.round(size * 100) / 100;
  71. const formattedSize = Number.isInteger(rounded) ? rounded : rounded.toFixed(2);
  72. return `${formattedSize} ${sizes[i]}`;
  73. }
  74. /**
  75. * Formats the timestamp into a human-readable string.
  76. *
  77. * @param {number} timestamp - The timestamp to format.
  78. * @returns {string} The formatted timestamp string.
  79. */
  80. export function formatTimestamp(timestamp: number): string {
  81. const date = getLocalizedDateFormatter(timestamp);
  82. const monthDay = date.format('MMM D'); // Eg. "May 15"
  83. const time = date.format('h:mm A'); // Eg. "2:30 PM"
  84. return `${monthDay}\n${time}`;
  85. }
  86. /**
  87. * Processes a list of files for upload.
  88. *
  89. * @param {FileList|File[]} fileList - The list of files to process.
  90. * @param {Dispatch} dispatch - The Redux dispatch function.
  91. * @returns {void}
  92. */
  93. // @ts-ignore
  94. export const processFiles = (fileList: FileList | File[], store: IStore) => {
  95. const state = store.getState();
  96. const dispatch = store.dispatch;
  97. const { maxFileSize = MAX_FILE_SIZE } = state['features/base/config']?.fileSharing ?? {};
  98. const newFiles = Array.from(fileList as File[]).filter((file: File) => {
  99. // No file size limitation
  100. if (maxFileSize === -1) {
  101. return true;
  102. }
  103. // Check file size before upload
  104. if (file.size > maxFileSize) {
  105. dispatch(showErrorNotification({
  106. titleKey: 'fileSharing.fileTooLargeTitle',
  107. descriptionKey: 'fileSharing.fileTooLargeDescription',
  108. descriptionArguments: {
  109. maxFileSize: formatFileSize(maxFileSize)
  110. },
  111. appearance: NOTIFICATION_TYPE.ERROR
  112. }, NOTIFICATION_TIMEOUT_TYPE.STICKY));
  113. return false;
  114. }
  115. return true;
  116. });
  117. if (newFiles.length > 0) {
  118. dispatch(uploadFiles(newFiles as File[]));
  119. }
  120. };
  121. /**
  122. * Determines if file uploading is enabled based on JWT feature flags and file sharing settings.
  123. *
  124. * @param {IReduxState} state - Current state.
  125. * @returns {boolean} Indication of whether local user can upload files.
  126. */
  127. export function isFileUploadingEnabled(state: IReduxState): boolean {
  128. return isJwtFeatureEnabled(state, MEET_FEATURES.FILE_UPLOAD, false) && isFileSharingEnabled(state);
  129. }