UNPKG

trtc-electron-sdk

Version:

trtc electron sdk

216 lines (215 loc) 7.88 kB
"use strict"; 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;