@tencentcloud/trtc-cloud-wx 0.0.25 → 0.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/.babelrc +6 -0
  2. package/.eslintrc.json +129 -0
  3. package/build/chokidar.js +19 -0
  4. package/build/clear.js +24 -0
  5. package/build/copy.js +24 -0
  6. package/build/copy_to_roomkit.js +19 -0
  7. package/dist/package.json +15 -0
  8. package/{trtc-cloud-wx.js → dist/trtc-cloud-wx.js} +146 -1
  9. package/docs/API/TRTCCloud.html +4353 -0
  10. package/docs/API/index.html +98 -0
  11. package/docs/API/scripts/add-toc.js +57 -0
  12. package/docs/API/scripts/collapse.js +20 -0
  13. package/docs/API/scripts/highlight/highlight.min.js +1282 -0
  14. package/docs/API/scripts/highlight/highlightjs-line-numbers.min.js +1 -0
  15. package/docs/API/scripts/linenumber.js +25 -0
  16. package/docs/API/scripts/nav.js +12 -0
  17. package/docs/API/scripts/polyfill.js +4 -0
  18. package/docs/API/scripts/prettify/Apache-License-2.0.txt +202 -0
  19. package/docs/API/scripts/prettify/lang-css.js +2 -0
  20. package/docs/API/scripts/prettify/prettify.js +28 -0
  21. package/docs/API/scripts/search.js +83 -0
  22. package/docs/API/styles/font.css +81 -0
  23. package/docs/API/styles/fonts/JTURjIg1_i6t8kCHKm45_dJE3g3D_vx3rCubqg.woff2 +0 -0
  24. package/docs/API/styles/fonts/JTURjIg1_i6t8kCHKm45_dJE3gTD_vx3rCubqg.woff2 +0 -0
  25. package/docs/API/styles/fonts/JTURjIg1_i6t8kCHKm45_dJE3gbD_vx3rCubqg.woff2 +0 -0
  26. package/docs/API/styles/fonts/JTURjIg1_i6t8kCHKm45_dJE3gfD_vx3rCubqg.woff2 +0 -0
  27. package/docs/API/styles/fonts/JTURjIg1_i6t8kCHKm45_dJE3gnD_vx3rCs.woff2 +0 -0
  28. package/docs/API/styles/fonts/JTUSjIg1_i6t8kCHKm459W1hyyTh89ZNpQ.woff2 +0 -0
  29. package/docs/API/styles/fonts/JTUSjIg1_i6t8kCHKm459WRhyyTh89ZNpQ.woff2 +0 -0
  30. package/docs/API/styles/fonts/JTUSjIg1_i6t8kCHKm459WZhyyTh89ZNpQ.woff2 +0 -0
  31. package/docs/API/styles/fonts/JTUSjIg1_i6t8kCHKm459WdhyyTh89ZNpQ.woff2 +0 -0
  32. package/docs/API/styles/fonts/JTUSjIg1_i6t8kCHKm459WlhyyTh89Y.woff2 +0 -0
  33. package/docs/API/styles/highlight/highlight.min.css +26 -0
  34. package/docs/API/styles/highlight/rainbow.min.css +1 -0
  35. package/docs/API/styles/jsdoc.css +684 -0
  36. package/docs/API/styles/prettify.css +79 -0
  37. package/docs/API/styles/toc.css +44 -0
  38. package/docs/API/tutorial-00-guideline.html +81 -0
  39. package/docs/doc-src/home.md +7 -0
  40. package/docs/doc-src/tutorials/00-guideline.md +1 -0
  41. package/docs/doc-src/tutorials/tutorials.json +5 -0
  42. package/jsdoc.json +43 -0
  43. package/package.json +44 -3
  44. package/rollup.config.js +19 -0
  45. package/sdk_publish.bash +5 -0
  46. package/src/TaskMachine.ts +368 -0
  47. package/src/deviceAuthorize.ts +75 -0
  48. package/src/index.ts +1091 -0
  49. package/src/interface/index.ts +44 -0
  50. package/src/interface/types.ts +88 -0
  51. package/src/log/logger.ts +103 -0
  52. package/src/types.d.ts +1 -0
  53. package/src/utils/common.ts +67 -0
  54. package/src/utils/index.ts +2 -0
  55. package/src/utils/translate.ts +125 -0
  56. package/tsconfig.json +15 -0
  57. package/typedoc.json +21 -0
@@ -0,0 +1,368 @@
1
+ export enum Handletype {
2
+ setPusher = 'setPusher',
3
+ setPlayer = 'setPlayer'
4
+ }
5
+ // 数字越高,set优先级越高
6
+ export const TaskMap = {
7
+ enterRoom: {priority: 0, type: Handletype.setPusher},
8
+ switchRole: {priority: 1, type: Handletype.setPusher},
9
+ startLocalPreview: {priority: 0, type: Handletype.setPusher},
10
+ stopLocalPreview: {priority: 0, type: Handletype.setPusher},
11
+ muteLocalVideo: {priority: 1, type: Handletype.setPusher},
12
+ setVideoEncoderParam: {priority: 0, type: Handletype.setPusher},
13
+ setLocalRenderParams: {priority: 0, type: Handletype.setPusher},
14
+ startLocalAudio: {priority: 0, type: Handletype.setPusher},
15
+ stopLocalAudio: {priority: 0, type: Handletype.setPusher},
16
+ muteLocalAudio: {priority: 1, type: Handletype.setPusher},
17
+ switchCamera: {priority: 0, type: Handletype.setPusher},
18
+ setBeautyStyle: {priority: 0, type: Handletype.setPusher},
19
+ exitRoom: {priority: 9, type: Handletype.setPusher},
20
+ startRemoteView: {priority: 0, type: Handletype.setPlayer},
21
+ updateRemoteView: {priority: 0, type: Handletype.setPlayer},
22
+ stopAllRemoteView: {priority: 1, type: Handletype.setPlayer},
23
+ muteRemoteVideoStream: {priority: 1, type: Handletype.setPlayer},
24
+ muteAllRemoteVideoStreams: {priority: 1, type: Handletype.setPlayer},
25
+ setRemoteRenderParams: {priority: 0, type: Handletype.setPlayer},
26
+ muteRemoteAudio: {priority: 1, type: Handletype.setPlayer},
27
+ muteAllRemoteAudio: {priority: 1, type: Handletype.setPlayer},
28
+ }
29
+ interface TaskOptions {
30
+ ctx: any;
31
+ priority?: number;
32
+ action: Function;
33
+ args: any;
34
+ resolve: Function;
35
+ reject: Function;
36
+ name: string;
37
+ }
38
+ class Task {
39
+ public ctx: any;
40
+
41
+ public priority: number;
42
+
43
+ public action: Function
44
+
45
+ public sequenceNumber: number
46
+
47
+ public args: any
48
+
49
+ public resolve: Function
50
+
51
+ public reject: Function
52
+
53
+ public name: string
54
+
55
+ public single: boolean
56
+
57
+ public type: Handletype
58
+
59
+ public result: any
60
+
61
+ public err: any
62
+
63
+ static nextSequenceNumber = 0;
64
+
65
+
66
+ constructor(optinos: TaskOptions) {
67
+ const {
68
+ priority = 0, action, args, resolve, reject, ctx, name
69
+ } = optinos
70
+ this.ctx = ctx
71
+ this.priority = priority
72
+ this.action = action
73
+ this.args = args
74
+ this.resolve = resolve
75
+ this.reject = reject
76
+ this.name = name
77
+ this.single = this.whetherSingle(name)
78
+ this.type = TaskMap[name]?.type || Handletype.setPusher
79
+ this.sequenceNumber = Task.nextSequenceNumber++
80
+ }
81
+
82
+ whetherSingle(funName: string): boolean {
83
+ switch (funName) {
84
+ case 'enterRoom':
85
+ return true
86
+ default:
87
+ return false
88
+ }
89
+ }
90
+ }
91
+
92
+ export enum TaskQueueState {
93
+ IDLE = 'idle',
94
+ PENDING = 'pending',
95
+ PROCESS = 'process',
96
+ }
97
+
98
+ export enum TaskQueueEvent {
99
+ SET = 'SET',
100
+ SETPROCESS = 'SETPROCESS',
101
+ SETDONE = 'SETDONE',
102
+ }
103
+
104
+ export class TaskMachine {
105
+ public state: TaskQueueState;
106
+
107
+ private isProcessing = false; // 表示 pusherTaskQueue 是否正在处理
108
+
109
+ private pusherDomReady = false
110
+
111
+ private pusherTaskQueue = [] as Task[]; // 存储所有 pusher 任务
112
+
113
+ private playerTasks: Record<
114
+ string, {taskQueue: Task[]; isProcessing: boolean; domReady: boolean}
115
+ > = {}; // 存储每个 player 的任务队列
116
+
117
+ constructor() {
118
+ this.state = TaskQueueState.IDLE
119
+ }
120
+
121
+ reset(): void {
122
+ this.state = TaskQueueState.IDLE
123
+ this.resetPusherTasks()
124
+ for (const key in this.playerTasks) {
125
+ if (this.playerTasks[key]) {
126
+ this.resetPlayerTasks(key)
127
+ }
128
+ }
129
+ this.playerTasks = {}
130
+ }
131
+
132
+ resetPusherTasks(): void {
133
+ this.isProcessing = false
134
+ this.pusherDomReady = false
135
+ this.pusherTaskQueue.forEach((task) => {
136
+ task.resolve()
137
+ })
138
+ this.pusherTaskQueue.length = 0
139
+ }
140
+
141
+ resetPlayerTasks(view: string): void {
142
+ if (this.playerTasks[view]) {
143
+ this.playerTasks[view].taskQueue.forEach(task => {
144
+ task.resolve()
145
+ })
146
+ this.playerTasks[view].taskQueue.length = 0
147
+ this.playerTasks[view].isProcessing = false
148
+ this.playerTasks[view].domReady = false
149
+ }
150
+ }
151
+
152
+ setPusherDomReady(isReady: boolean): boolean {
153
+ this.pusherDomReady = isReady
154
+ if (!isReady) {
155
+ this.resetPusherTasks()
156
+ }
157
+ return this.pusherDomReady
158
+ }
159
+
160
+ setPlayerDomReady(view: string, isReady: boolean): void {
161
+ if (!this.playerTasks[view]) {
162
+ this.playerTasks[view] = {taskQueue: [], isProcessing: false, domReady: false}
163
+ }
164
+ this.playerTasks[view].domReady = isReady
165
+ if (isReady) {
166
+ this.processPlayerTasks(view)
167
+ } else {
168
+ this.resetPlayerTasks(view)
169
+ }
170
+ }
171
+
172
+ send(event: TaskQueueEvent, view?: string): void {
173
+ switch (this.state) {
174
+ case TaskQueueState.IDLE:
175
+ if (event === TaskQueueEvent.SET) {
176
+ this.state = TaskQueueState.PENDING
177
+ if (view) {
178
+ this.processPlayerTasks(view)
179
+ } else {
180
+ this.processPusherTasks()
181
+ }
182
+ }
183
+ break
184
+ case TaskQueueState.PENDING:
185
+ if (event === TaskQueueEvent.SETPROCESS) {
186
+ if (view) {
187
+ this.processPlayerTasks(view)
188
+ } else {
189
+ this.processPusherTasks()
190
+ }
191
+ }
192
+ if (event === TaskQueueEvent.SETDONE) {
193
+ this.state = TaskQueueState.IDLE
194
+ }
195
+ break
196
+ case TaskQueueState.PROCESS:
197
+ if (event === TaskQueueEvent.SETDONE) {
198
+ this.state = TaskQueueState.IDLE
199
+ }
200
+ break
201
+ default:
202
+ break
203
+ }
204
+ }
205
+
206
+ addTask(task: Task): void {
207
+ if (task.type === Handletype.setPusher) {
208
+ this.addPusherTask(task)
209
+ } else {
210
+ this.addPlayerTask(task.args.view, task)
211
+ }
212
+ }
213
+
214
+ private addPusherTask(task: Task): void {
215
+ this.addTaskToQueue(task, this.pusherTaskQueue)
216
+ if (this.state === TaskQueueState.PROCESS && !this.isProcessing) {
217
+ this.processPusherTasks()
218
+ } else if (this.state === TaskQueueState.IDLE) {
219
+ this.send(TaskQueueEvent.SET)
220
+ } else if (this.state === TaskQueueState.PENDING) {
221
+ this.send(TaskQueueEvent.SETPROCESS)
222
+ }
223
+ }
224
+
225
+ private addPlayerTask(view: string, task: Task): void {
226
+ if (!this.playerTasks[view]) {
227
+ this.playerTasks[view] = {taskQueue: [], isProcessing: false, domReady: false}
228
+ }
229
+ this.addTaskToQueue(task, this.playerTasks[view].taskQueue)
230
+ if (this.state === TaskQueueState.PROCESS && !this.playerTasks[view].isProcessing) {
231
+ this.processPlayerTasks(view)
232
+ } else if (this.state === TaskQueueState.IDLE) {
233
+ this.send(TaskQueueEvent.SET, view)
234
+ } else if (this.state === TaskQueueState.PENDING) {
235
+ this.send(TaskQueueEvent.SETPROCESS, view)
236
+ }
237
+ }
238
+
239
+ private addTaskToQueue(task: Task, queue: Task[]): void {
240
+ queue.push(task)
241
+ queue.sort((a, b) => {
242
+ if (a.priority !== b.priority) {
243
+ return a.priority - b.priority
244
+ }
245
+ return a.sequenceNumber - b.sequenceNumber
246
+ })
247
+ }
248
+
249
+ /**
250
+ * 处理任务队列
251
+ * @param taskQueue
252
+ * @param isProcessing
253
+ * @param domReady
254
+ * @param setProcessing
255
+ * @returns
256
+ */
257
+ private async processTasks(
258
+ taskQueue: Task[],
259
+ isProcessing: boolean,
260
+ domReady: boolean,
261
+ setProcessing: (value: boolean) => void,
262
+ view?: string
263
+ ): Promise<void> {
264
+ if (isProcessing || !domReady || taskQueue.length === 0) return
265
+ setProcessing(true)
266
+ this.state = TaskQueueState.PROCESS
267
+
268
+ const currentTasks = [...taskQueue]
269
+ taskQueue.length = 0
270
+ const singleTasks = currentTasks.filter(task => task.single)
271
+ const exceptSingleTask = currentTasks.filter(task => !task.single)
272
+
273
+ for (const task of singleTasks) {
274
+ try {
275
+ task.result = await task.action.call(task.ctx, task.args, task.name, TaskMap[task.name].type)
276
+ } catch (err) {
277
+ task.err = err
278
+ }
279
+ }
280
+
281
+ const params = exceptSingleTask.reduce(
282
+ (acc, cur) => {
283
+ const params = cur.args.params
284
+ return {...acc, ...(typeof params === 'function' ? params() : params)}
285
+ }, {}
286
+ )
287
+ const task = exceptSingleTask[0]
288
+ const sequenceTask = currentTasks.sort((a, b) => a.sequenceNumber - b.sequenceNumber)
289
+ try {
290
+ let r = null
291
+ if (task) {
292
+ view
293
+ ? r = await task.action.call(
294
+ task.ctx,
295
+ {params, streamId: task.args.streamId, view},
296
+ task.name,
297
+ Handletype.setPlayer
298
+ )
299
+ : r = await task.action.call(task.ctx, {params}, task.name, Handletype.setPusher)
300
+ }
301
+
302
+ for (const task of sequenceTask) {
303
+ if (task.err) {
304
+ task.reject(task.err)
305
+ } else {
306
+ task.resolve(task.result || r)
307
+ }
308
+ }
309
+ } catch (err) {
310
+ for (const task of sequenceTask) {
311
+ task.reject(err)
312
+ }
313
+ }
314
+
315
+ setProcessing(false)
316
+ this.send(TaskQueueEvent.SETDONE, view)
317
+
318
+ if (taskQueue.length > 0) {
319
+ Promise.resolve().then(() => {
320
+ this.processTasks(taskQueue, isProcessing, domReady, setProcessing, view)
321
+ }).catch(console.error)
322
+ }
323
+ }
324
+
325
+ private async processPusherTasks(): Promise<void> {
326
+ await this.processTasks(
327
+ this.pusherTaskQueue,
328
+ this.isProcessing,
329
+ this.pusherDomReady,
330
+ (value) => { this.isProcessing = value }
331
+ )
332
+ }
333
+
334
+ private async processPlayerTasks(view: string): Promise<void> {
335
+ if (!this.playerTasks[view]) return
336
+ await this.processTasks(
337
+ this.playerTasks[view].taskQueue,
338
+ this.playerTasks[view].isProcessing,
339
+ this.playerTasks[view].domReady,
340
+ (value) => { this.playerTasks[view].isProcessing = value },
341
+ view
342
+ )
343
+ }
344
+ }
345
+ export const taskMachine = new TaskMachine()
346
+
347
+ export const setHandle = (target: any, key: string, descriptor: PropertyDescriptor): PropertyDescriptor => {
348
+ const originalMethod = descriptor.value
349
+ descriptor.value = function (...args: any): Promise<any> {
350
+ const [params, funName] = args
351
+ return new Promise((resolve, reject) => {
352
+ try {
353
+ taskMachine.addTask(new Task({
354
+ ctx: this,
355
+ priority: TaskMap[funName]?.priority || 0,
356
+ action: originalMethod,
357
+ args: params,
358
+ name: funName,
359
+ resolve,
360
+ reject
361
+ }))
362
+ } catch (error) {
363
+ reject(error)
364
+ }
365
+ })
366
+ }
367
+ return descriptor
368
+ }
@@ -0,0 +1,75 @@
1
+ import {debounce} from './utils'
2
+
3
+ export enum DeviceScope {
4
+ RECORD = 'scope.record',
5
+ CAMERA = 'scope.camera'
6
+ }
7
+ export enum DeviceType {
8
+ MIC = 'mic',
9
+ CAMERA = 'camera'
10
+ }
11
+ /**
12
+ * 获取设备权限,查看当前是否有麦克风以及摄像头权限
13
+ * @param {Object} params - 参数对象
14
+ * @param {Boolean} params.microphone 麦克风权限
15
+ * @param {Boolean} params.camera 摄像头权限
16
+ */
17
+ async function deviceCheck(types: Array<DeviceType>): Promise<boolean> {
18
+ if (!types) return false
19
+ const microphone = types.includes(DeviceType.MIC)
20
+ const camera = types.includes(DeviceType.CAMERA)
21
+ try {
22
+ const res = await wx.getSetting()
23
+ const isMicrophone = res.authSetting[DeviceScope.RECORD]
24
+ const isCamera = res.authSetting[DeviceScope.CAMERA]
25
+ // 同时检查麦克风和摄像头权限
26
+ if (microphone && camera) {
27
+ return isMicrophone && isCamera
28
+ }
29
+ // 只检查麦克风权限
30
+ if (microphone) {
31
+ return isMicrophone
32
+ }
33
+ // 只检查摄像头权限
34
+ if (camera) {
35
+ return isCamera
36
+ }
37
+ return false
38
+ } catch (error) {
39
+ return false
40
+ }
41
+ }
42
+
43
+
44
+ function permissionPopup(): void {
45
+ wx.showModal({
46
+ title: '设备授权',
47
+ content: '使用音视频功能请对相应设备进行授权',
48
+ confirmText: '去设置',
49
+ success: (res) => {
50
+ if (res.confirm) {
51
+ wx.openSetting()
52
+ }
53
+ },
54
+ })
55
+ }
56
+ const debouncePermissionPopup = debounce(permissionPopup, 300)
57
+ export function deviceAuthorize(deviceType: DeviceType, scope: DeviceScope) {
58
+ return function (target: any, key: string, descriptor: PropertyDescriptor): PropertyDescriptor {
59
+ const originalMethod = descriptor.value
60
+ descriptor.value = async function (...args: any[]): Promise<any> {
61
+ if (!await deviceCheck([deviceType])) {
62
+ try {
63
+ await wx.authorize({scope})
64
+ } catch (error) {
65
+ debouncePermissionPopup()
66
+ throw new Error(error)
67
+ }
68
+ return
69
+ }
70
+ // eslint-disable-next-line consistent-return
71
+ return originalMethod.apply(this, args)
72
+ }
73
+ return descriptor
74
+ }
75
+ }