trtc-electron-sdk
Version:
trtc electron sdk
216 lines (215 loc) • 7.88 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.toIndependentArrayBuffer = exports.normalizeSEIPayload = exports.isLinux = exports.isWindows = exports.isMacOS = exports.getOS = exports.throttle = exports.debounce = exports.convertUint8ArrayToNumber = exports.safelyParse = exports.isNullOrUndefined = exports.isUndefined = exports.isNull = void 0;
function isNull(val) {
return val === null;
}
exports.isNull = isNull;
function isUndefined(val) {
return val === undefined;
}
exports.isUndefined = isUndefined;
function isNullOrUndefined(val) {
return val === null || val === undefined;
}
exports.isNullOrUndefined = isNullOrUndefined;
/**
* 安全执行 JSON.parse
* @param data
* @returns
*/
function safelyParse(data) {
if (typeof data !== 'string') {
return data;
}
let result;
try {
const tempData = JSON.parse(data);
// 规避 JSON.parse('12345') 转化为 12345 的情况
if (typeof tempData === 'object' && tempData) {
result = tempData;
}
else {
result = data;
}
}
catch (error) {
result = data;
}
return result;
}
exports.safelyParse = safelyParse;
function convertUint8ArrayToNumber(value) {
let result = 0;
for (let i = value.length - 1; i >= 0; i--) {
result = (result * 256) + value[i];
}
return result;
}
exports.convertUint8ArrayToNumber = convertUint8ArrayToNumber;
/**
* 防抖函数 (debounce)
*
* 适用场景:搜索框输入联想、窗口resize结束事件
*
* @param func 需要防抖的函数
* @param wait 等待时间(毫秒)
* @param immediate 是否立即执行第一次调用(true=立即执行,false=等待后执行)
* @returns 包装后的防抖函数
*/
function debounce(func, wait, immediate = false) {
let timeout = null;
let inWait = false; // 是否处于等待周期
return function (...args) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const context = this;
// 每次调用都清除现有定时器
if (timeout)
clearTimeout(timeout);
if (immediate && !inWait) {
// 立即执行模式且不在等待期
func.apply(context, args);
inWait = true;
}
// 设置新定时器
timeout = setTimeout(() => {
inWait = false;
if (!immediate) {
// 非立即执行模式:执行最后一次调用
func.apply(context, args);
}
}, wait);
};
}
exports.debounce = debounce;
/**
* 节流函数 (throttle)
*
* 适用场景:滚动事件、按钮防重复点击、鼠标移动事件
*
* @param func 需要节流的函数
* @param wait 等待时间(毫秒)
* @param options 配置选项
* leading: 是否执行第一次调用(true=执行,false=跳过)
* trailing: 是否执行最后一次调用(true=执行,false=跳过)
* @returns 包装后的节流函数
*/
function throttle(func, wait, options = {}) {
const { leading = true, trailing = true } = options;
let lastExecTime = 0;
let timer = null;
let savedContext = null, savedArgs = null;
// 实际执行函数
const execute = () => {
lastExecTime = Date.now();
timer = null;
if (savedContext !== null && savedArgs !== null) {
func.apply(savedContext, savedArgs);
}
};
return function (...args) {
savedContext = this;
savedArgs = args;
const now = Date.now();
// 计算距离上次执行的时间差
const sinceLast = now - lastExecTime;
const remaining = wait - sinceLast;
// 超时情况:立即执行(无论是否在等待期)
if (remaining <= 0 || remaining > wait) {
if (timer) {
clearTimeout(timer);
timer = null;
}
if (leading) {
execute();
}
}
else if (!timer && trailing) {
// 设置定时器执行尾部调用
timer = setTimeout(execute, remaining);
}
};
}
exports.throttle = throttle;
function getOS() {
var _a, _b;
let os = '';
if (process && process.platform) {
os = process.platform;
}
else {
// @ts-ignore
const platform = ((_b = (_a = window.navigator) === null || _a === void 0 ? void 0 : _a.userAgentData) === null || _b === void 0 ? void 0 : _b.platform) || window.navigator.platform;
const macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K', 'macOS'];
const windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'];
if (macosPlatforms.indexOf(platform) !== -1) {
os = 'darwin';
}
else if (windowsPlatforms.indexOf(platform) !== -1) {
os = 'win32';
}
else if (/Linux/.test(platform)) {
os = 'linux';
}
}
return os;
}
exports.getOS = getOS;
function isMacOS() {
return getOS() === 'darwin';
}
exports.isMacOS = isMacOS;
function isWindows() {
return getOS() === 'win32';
}
exports.isWindows = isWindows;
function isLinux() {
return getOS() === 'linux';
}
exports.isLinux = isLinux;
// ─── SEI 二进制收发编解码 ───────────────────────────────────────────
//
// 供中文/英文两版 TRTCCloud 共用,避免在 trtc.ts / trtc_en.ts 维护两份
// 完全一致的本地化逻辑。
/**
* 把 sendSEIMsg 的 JS 入参(ArrayBuffer / TypedArray / DataView 等)规范化为 Uint8Array。
*
* - 字符串入参不再支持,由调用方自行 `TextEncoder().encode(...)` 后传入;
* - 对 TypedArray / DataView 视图保留原始 byteOffset / byteLength,不会把整段底层
* ArrayBuffer 当成数据;
* - 类型不匹配时抛 `TypeError`,与 Native 层的报错文案保持一致。
*/
function normalizeSEIPayload(input) {
if (input instanceof ArrayBuffer) {
return new Uint8Array(input);
}
if (ArrayBuffer.isView(input)) {
return new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
}
throw new TypeError('sendSEIMsg: msg must be ArrayBuffer, TypedArray or Buffer');
}
exports.normalizeSEIPayload = normalizeSEIPayload;
/**
* 把 native 回调里收到的二进制对象(Uint8Array / Buffer / ArrayBuffer)统一转成
* 一个 **独立的** ArrayBuffer,对外暴露给业务层。
*
* 为什么要"独立":
* - Node Buffer / TypedArray 的 `.buffer` 是 native 复用的存储区,可能被后续事件
* 覆写;直接 fire 出去会出现"业务层拿到的 message 跟下一帧消息字节错乱"。
* - 这里通过 `new ArrayBuffer + Uint8Array.set` 显式拷贝,避免 `slice() as ArrayBuffer`
* 的不严谨断言(slice 返回类型为 `ArrayBufferLike`,可能是 SharedArrayBuffer)。
*/
function toIndependentArrayBuffer(message) {
if (message instanceof ArrayBuffer) {
// 收到的就是裸 ArrayBuffer 时也做一次拷贝,统一上层语义:
// "事件回调里拿到的 message 永远是一份独立内存"。
const copy = new ArrayBuffer(message.byteLength);
new Uint8Array(copy).set(new Uint8Array(message));
return copy;
}
// Uint8Array / Buffer 共用的视图分支。
const copy = new ArrayBuffer(message.byteLength);
new Uint8Array(copy).set(message);
return copy;
}
exports.toIndependentArrayBuffer = toIndependentArrayBuffer;