142 lines
4.0 KiB
TypeScript
142 lines
4.0 KiB
TypeScript
/**
|
|
* Copyright 2025 Beijing Volcano Engine Technology Co., Ltd. All Rights Reserved.
|
|
* SPDX-license-identifier: BSD-3-Clause
|
|
*/
|
|
|
|
import { Msg, RoomState } from '@/store/slices/room';
|
|
import RtcClient from '@/lib/RtcClient';
|
|
|
|
class Utils {
|
|
formatTime = (time: number): string => {
|
|
if (time < 0) {
|
|
return '00:00';
|
|
}
|
|
let minutes: number | string = Math.floor(time / 60);
|
|
let seconds: number | string = time % 60;
|
|
minutes = minutes > 9 ? `${minutes}` : `0${minutes}`;
|
|
seconds = seconds > 9 ? `${seconds}` : `0${seconds}`;
|
|
|
|
return `${minutes}:${seconds}`;
|
|
};
|
|
|
|
formatDate = (date: Date): string => {
|
|
const hours = date.getHours();
|
|
const minutes = date.getMinutes();
|
|
const seconds = date.getSeconds();
|
|
|
|
const formattedHours = hours.toString().padStart(2, '0');
|
|
const formattedMinutes = minutes.toString().padStart(2, '0');
|
|
const formattedSeconds = seconds.toString().padStart(2, '0');
|
|
|
|
return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
|
|
};
|
|
|
|
setSessionInfo = (params: { [key: string]: any }) => {
|
|
Object.keys(params).forEach((key) => {
|
|
sessionStorage.setItem(key, params[key]);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* @brief 获取 url 参数
|
|
*/
|
|
getUrlArgs = () => {
|
|
const query = window.location.search.substring(1);
|
|
const pairs = query.split('&');
|
|
return pairs.reduce<{ [key: string]: string }>((queries, pair) => {
|
|
const [key, value] = decodeURIComponent(pair).split('=');
|
|
if (key && value) {
|
|
queries[key] = value;
|
|
}
|
|
return queries;
|
|
}, {});
|
|
};
|
|
|
|
isPureObject = (target: any) => Object.prototype.toString.call(target).includes('Object');
|
|
|
|
isArray = Array.isArray;
|
|
|
|
debounce = (func: (...args: any[]) => void, wait: number) => {
|
|
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
return function (...args: any[]) {
|
|
if (timeoutId !== null) {
|
|
clearTimeout(timeoutId);
|
|
}
|
|
|
|
timeoutId = setTimeout(() => {
|
|
func(...args);
|
|
}, wait);
|
|
};
|
|
};
|
|
|
|
addMsgWithoutDuplicate = (arr: RoomState['msgHistory'], added: Msg) => {
|
|
if (arr.length) {
|
|
const last = arr.at(-1)!;
|
|
const { user, value, isInterrupted } = last;
|
|
if ((added.user === RtcClient.basicInfo.user_id && last.user === added.user) || (user === added.user && added.value.startsWith(value) && value.trim())) {
|
|
arr.pop();
|
|
added.isInterrupted = isInterrupted;
|
|
}
|
|
}
|
|
arr.push(added);
|
|
};
|
|
|
|
/**
|
|
* @brief 将字符串包装成 TLV
|
|
*/
|
|
string2tlv(str: string, type: string) {
|
|
const typeBuffer = new Uint8Array(4);
|
|
|
|
for (let i = 0; i < type.length; i++) {
|
|
typeBuffer[i] = type.charCodeAt(i);
|
|
}
|
|
|
|
const lengthBuffer = new Uint32Array(1);
|
|
const valueBuffer = new TextEncoder().encode(str);
|
|
|
|
lengthBuffer[0] = valueBuffer.length;
|
|
|
|
const tlvBuffer = new Uint8Array(typeBuffer.length + 4 + valueBuffer.length);
|
|
|
|
tlvBuffer.set(typeBuffer, 0);
|
|
|
|
tlvBuffer[4] = (lengthBuffer[0] >> 24) & 0xff;
|
|
tlvBuffer[5] = (lengthBuffer[0] >> 16) & 0xff;
|
|
tlvBuffer[6] = (lengthBuffer[0] >> 8) & 0xff;
|
|
tlvBuffer[7] = lengthBuffer[0] & 0xff;
|
|
|
|
tlvBuffer.set(valueBuffer, 8);
|
|
return tlvBuffer.buffer;
|
|
}
|
|
|
|
/**
|
|
* @brief TLV 数据格式转换成字符串
|
|
* @note TLV 数据格式
|
|
* | magic number | length(big-endian) | value |
|
|
* @param {ArrayBufferLike} tlvBuffer
|
|
* @returns
|
|
*/
|
|
tlv2String(tlvBuffer: ArrayBufferLike) {
|
|
const typeBuffer = new Uint8Array(tlvBuffer, 0, 4);
|
|
const lengthBuffer = new Uint8Array(tlvBuffer, 4, 4);
|
|
const valueBuffer = new Uint8Array(tlvBuffer, 8);
|
|
|
|
let type = '';
|
|
for (let i = 0; i < typeBuffer.length; i++) {
|
|
type += String.fromCharCode(typeBuffer[i]);
|
|
}
|
|
|
|
const length = (lengthBuffer[0] << 24) | (lengthBuffer[1] << 16) | (lengthBuffer[2] << 8) | lengthBuffer[3];
|
|
|
|
const value = new TextDecoder().decode(valueBuffer.subarray(0, length));
|
|
|
|
return { type, value };
|
|
}
|
|
|
|
isMobile() {
|
|
return /Mobi|Android|iPhone|iPad|Windows Phone/i.test(window.navigator.userAgent);
|
|
}
|
|
}
|
|
|
|
export default new Utils();
|