utils.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import TUIChatEngine, { TUITranslateService, TUIStore, StoreName, IMessageModel } from '@tencentcloud/chat-uikit-engine';
  2. import { Toast, TOAST_TYPE } from '../../common/Toast/index';
  3. export function deepCopy(data: any, hash = new WeakMap()) {
  4. if (typeof data !== 'object' || data === null || data === undefined) {
  5. return data;
  6. }
  7. if (hash.has(data)) {
  8. return hash.get(data);
  9. }
  10. const newData: any = Object.create(Object.getPrototypeOf(data));
  11. const dataKeys = Object.keys(data);
  12. dataKeys.forEach((value) => {
  13. const currentDataValue = data[value];
  14. if (typeof currentDataValue !== 'object' || currentDataValue === null) {
  15. newData[value] = currentDataValue;
  16. } else if (Array.isArray(currentDataValue)) {
  17. newData[value] = [...currentDataValue];
  18. } else if (currentDataValue instanceof Set) {
  19. newData[value] = new Set([...currentDataValue]);
  20. } else if (currentDataValue instanceof Map) {
  21. newData[value] = new Map([...currentDataValue]);
  22. } else {
  23. hash.set(data, data);
  24. newData[value] = deepCopy(currentDataValue, hash);
  25. }
  26. });
  27. return newData;
  28. }
  29. export const handleSkeletonSize = (
  30. width: number,
  31. height: number,
  32. maxWidth: number,
  33. maxHeight: number,
  34. ): { width: number; height: number } => {
  35. const widthToHeight = width / height;
  36. const maxWidthToHeight = maxWidth / maxHeight;
  37. if (width <= maxWidth && height <= maxHeight) {
  38. return { width, height };
  39. }
  40. if (
  41. (width <= maxWidth && height > maxHeight)
  42. || (width > maxWidth && height > maxHeight && widthToHeight <= maxWidthToHeight)
  43. ) {
  44. return { width: width * (maxHeight / height), height: maxHeight };
  45. }
  46. return { width: maxWidth, height: height * (maxWidth / width) };
  47. };
  48. // Image loading complete
  49. export function getImgLoad(container: any, className: string, callback: any) {
  50. const images = container?.querySelectorAll(`.${className}`) || [];
  51. const promiseList = Array.prototype.slice.call(images).map((node: any) => {
  52. return new Promise((resolve: any) => {
  53. node.onload = () => {
  54. resolve(node);
  55. };
  56. node.onloadeddata = () => {
  57. resolve(node);
  58. };
  59. node.onprogress = () => {
  60. resolve(node);
  61. };
  62. if (node.complete) {
  63. resolve(node);
  64. }
  65. });
  66. });
  67. return Promise.all(promiseList)
  68. .then(() => {
  69. callback && callback();
  70. })
  71. .catch((e) => {
  72. console.error('网络异常', e);
  73. });
  74. }
  75. export const isCreateGroupCustomMessage = (message: IMessageModel) => {
  76. return (
  77. message.type === TUIChatEngine.TYPES.MSG_CUSTOM
  78. && message?.getMessageContent()?.businessID === 'group_create'
  79. );
  80. };
  81. /**
  82. * displayMessageReadReceipt 用户级别控制展示消息阅读状态
  83. * 关闭后 你收发的消息均不带消息阅读状态
  84. * 你将无法看到对方是否已读 同时对方也无法看到他发送的消息你是否已读
  85. *
  86. * enabledMessageReadReceipt app级别是否开启已读回执
  87. *
  88. * @return {boolean} - Returns a boolean value indicating if the message read receipt is enabled globally.
  89. */
  90. export function isEnabledMessageReadReceiptGlobal(): boolean {
  91. return TUIStore.getData(StoreName.USER, 'displayMessageReadReceipt')
  92. && TUIStore.getData(StoreName.APP, 'enabledMessageReadReceipt');
  93. }
  94. export function shallowCopyMessage(message: IMessageModel) {
  95. return Object.assign({}, message);
  96. }
  97. export async function copyText(text: string) {
  98. const textString = text.toString();
  99. try {
  100. // 优先采用异步 copy navigator.clipboard 方案
  101. await navigator.clipboard.writeText(textString);
  102. } catch (err: any) {
  103. // 不支持 navigator.clipboard 时,走兼容替代方案
  104. copyTextByDocumentExecCommand(textString);
  105. }
  106. }
  107. function copyTextByDocumentExecCommand(textString: string) {
  108. const input = document.createElement('input');
  109. input.id = 'copy-input';
  110. input.readOnly = true; // Prevent IOS focus from triggering keyboard events
  111. input.style.position = 'absolute';
  112. input.style.left = '-1000px';
  113. input.style.zIndex = '-1000';
  114. document.body.appendChild(input);
  115. input.value = textString;
  116. selectText(input, 0, textString.length);
  117. if (document.execCommand('copy')) {
  118. document.execCommand('copy');
  119. } else {
  120. Toast({
  121. message: TUITranslateService.t('TUIChat.此机型暂不支持复制'),
  122. type: TOAST_TYPE.ERROR,
  123. });
  124. }
  125. input.blur();
  126. }
  127. function selectText(
  128. textbox: HTMLInputElement,
  129. startIndex: number,
  130. stopIndex: number,
  131. ) {
  132. if ((textbox as any).createTextRange) {
  133. // ie
  134. const range = (textbox as any).createTextRange();
  135. range.collapse(true);
  136. range.moveStart('character', startIndex); // start character
  137. range.moveEnd('character', stopIndex - startIndex); // end character
  138. range.select();
  139. } else {
  140. // firefox / chrome
  141. (textbox as any).setSelectionRange(startIndex, stopIndex);
  142. (textbox as any).focus();
  143. }
  144. }