@conecli/cone-render 0.10.1-shop3.32 → 0.10.1-shop3.33

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.
@@ -1 +1 @@
1
- import React, { useCallback, useEffect, useRef, useState } from 'react'
2
1
  isH5,
3
2
  addHttps,
4
3
  isH5AndJdShopView,
5
4
  draBusinessCustomReport,
6
5
  isJdAndIosDevice,
7
6
  FIRST = 'first',
8
7
  OTHER = 'other'
9
8
  (props: ComponentInterFace.CustomVideoProps, ref: any) => {
10
9
  const {
11
10
  isSystemVideo,
12
11
  style,
13
12
  videoStyle,
14
13
  src,
15
14
  width,
16
15
  height,
17
16
  controls,
18
17
  id,
19
18
  poster,
20
19
  autoplay: isvAutoplay,
21
20
  loop,
22
21
  showMuteBtn: isvShowMuteBtn,
23
22
  muteButtonPostion,
24
23
  showFullscreenBtn,
25
24
  muteBtnPicSrcObj,
26
25
  muteBtnClassName,
27
26
  muteBtnStyle,
28
27
  objectFit,
29
28
  mockAutoplay,
30
29
  threshold = 0.6,
31
30
  onPlayCallback,
32
31
  onPauseCallback,
33
32
  onVideoApiCall,
34
33
  inViewCallback,
35
34
  outViewCallback,
36
35
  floorData
37
36
  } = props
38
37
  const { wifiVideoAutoPlay, windowHeight } = global.info.sysInfo
39
38
  const isFollowAppVideoPlayStatus = global.getDynamicConfig(
40
39
  'isFollowAppVideoPlayStatus',
41
40
  )
42
41
  let showMuteBtn = isvShowMuteBtn
43
42
  let autoplay = isvAutoplay
44
43
  if (isSystemVideo) {
45
44
  showMuteBtn = false
46
45
  autoplay = wifiVideoAutoPlay
47
46
  } else {
48
47
  if (isvAutoplay && isFollowAppVideoPlayStatus) {
49
48
  autoplay = wifiVideoAutoPlay
50
49
  }
51
50
  }
52
51
  console.log(
53
52
  'CustomVideo',
54
53
  'isSystemVideo:',
55
54
  isSystemVideo,
56
55
  'wifiVideoAutoPlay:',
57
56
  wifiVideoAutoPlay,
58
57
  ',isvAutoplay:',
59
58
  isvAutoplay,
60
59
  ',isFollowAppVideoPlayStatus:',
61
60
  isFollowAppVideoPlayStatus,
62
61
  ',autoplay:',
63
62
  autoplay,
64
63
  ',id:',
65
64
  id,
66
65
  )
67
66
  const [videoMutedState, setVideoMutedState] = useState(MUTED)
68
67
  const lastPlayStatusRef = useRef(-1)
69
68
  const manualPauseStateRef = useRef(false)
70
69
  const initPlayStatusRef = useRef(false)
71
70
  const isInViewStateRef = useRef(false)
72
71
  const disposeRef = useRef<Function | null>()
73
72
  const initVideoTopRef = useRef(0)
74
73
  const initFloorIndexRef = useRef(-1)
75
74
  ref === null && (ref = useRef<HTMLVideoElement | null>())
76
75
 
77
76
  const handleIosFirstScreenReloadVideo = useCallback((type: PlayVideoType) => {
78
77
  const floorIndex = initFloorIndexRef.current
79
78
  console.log('🚀 ~ playVideo isJdAndIosDevice: ', isJdAndIosDevice, '~ autoplay: ', autoplay, '~ floorIndex: ', floorIndex);
80
79
  if (!isJdAndIosDevice) return
81
80
  if(!autoplay) return
82
81
  if (floorIndex < 0 || floorIndex > 4) return
83
82
  if (type === PlayVideoType.FIRST && ref && ref.current) {
84
83
  const rect = ref.current.getBoundingClientRect();
85
84
  console.log('🚀 ~ playVideo 节点初始距顶部距离: ', initVideoTopRef.current, '~ 节点高度: ', rect.height, '~ 可见阈值: , threshold: ', threshold, '~ winwindowHeight: ', windowHeight);
86
85
  if (initVideoTopRef.current + Number(rect.height * threshold) <= windowHeight) {
87
86
  ref.current.load();
88
87
  console.log('🚀 ~ playVideo ios且首屏且首次进入可视区域,重新load加载视频');
89
88
  }
90
89
  }
91
90
  }, [])
92
91
 
93
92
  const playVideo = useCallback((type = PlayVideoType.OTHER) => {
94
93
  if (ref && ref.current) {
95
94
  console.log(`CustomVideo id:${id} 开始播放视频`)
96
95
  const result = ref.current.play()
97
96
  result &&
98
97
  result
99
98
  .then(() => {
100
99
  console.log(`播放视频成功`)
101
100
  handleIosFirstScreenReloadVideo(type)
102
101
  })
103
102
  .catch(e => {
104
103
  console.log('CustomVideo playVideo ', e.name, ':', e.message)
105
104
  })
106
105
  }
107
106
  }, [])
108
107
 
109
108
  const pauseVideo = useCallback(() => {
110
109
  if (ref && ref.current) {
111
110
  console.log(`CustomVideo id:${id} 暂停视频`)
112
111
  ref.current.pause()
113
112
  }
114
113
  }, [])
115
114
 
116
115
  useEffect(() => {
117
116
  if (!isH5 || !ref.current) return
118
117
  const rect = ref.current.getBoundingClientRect();
119
118
  initVideoTopRef.current = rect.top;
120
119
  const containerNode = ref.current.closest('[data-container-id]')
121
120
  if (containerNode) {
122
121
  initFloorIndexRef.current = Number(containerNode.getAttribute('data-container-index'))
123
122
  }
124
123
  if (autoplay && mockAutoplay) {
125
124
 
126
125
  const callInitAutoplay = () => {
127
126
  console.log(
128
127
  `CustomVideo id:${id} 触发初始化autoplay callInitAutoplay`,
129
128
  )
130
129
  if (
131
130
  autoplay &&
132
131
  mockAutoplay &&
133
132
  !initPlayStatusRef.current &&
134
133
  isInViewStateRef.current &&
135
134
  ref.current.paused
136
135
  ) {
137
136
  playVideo()
138
137
  }
139
138
  }
140
139
  const onWeixinJSBridgeReady = e => {
141
140
  callInitAutoplay()
142
141
  }
143
142
  const onTouchstart = e => {
144
143
  callInitAutoplay()
145
144
  }
146
145
  const onScroll = e => {
147
146
  callInitAutoplay()
148
147
  }
149
148
  const onPlay = e => {
150
149
  if (!initPlayStatusRef.current) {
151
150
  const dispose = disposeRef.current
152
151
  dispose && dispose()
153
152
  disposeRef.current = null
154
153
  }
155
154
  initPlayStatusRef.current = true
156
155
  }
157
156
  document?.addEventListener('WeixinJSBridgeReady', onWeixinJSBridgeReady)
158
157
  document?.addEventListener('touchstart', onTouchstart)
159
158
  document?.addEventListener('scroll', onScroll)
160
159
  ref.current.addEventListener('play', onPlay)
161
160
  const dispose = () => {
162
161
  console.log('调用dispose')
163
162
  document?.removeEventListener(
164
163
  'WeixinJSBridgeReady',
165
164
  onWeixinJSBridgeReady,
166
165
  )
167
166
  document?.removeEventListener('touchstart', onTouchstart)
168
167
  document?.removeEventListener('scroll', onScroll)
169
168
  ref?.current?.removeEventListener('play', onPlay)
170
169
  }
171
170
  disposeRef.current = dispose
172
171
  }
173
172
  const handleVideoPlayApiCall = () => {
174
173
  if (!isH5 || !ref.current) return
175
174
  playVideo()
176
175
  manualPauseStateRef.current = false
177
176
  }
178
177
  const handleVideoPauseApiCall = () => {
179
178
  if (!isH5 || !ref.current) return
180
179
  manualPauseStateRef.current = true
181
180
  pauseVideo()
182
181
  }
183
182
 
184
183
  const handleVideoSeekApiCall = (position: number) => {
185
184
  if (!isH5 || !ref.current) return
186
185
  if (typeof position === 'undefined' || typeof position !== 'number')
187
186
  return
188
187
  ref.current.currentTime = position
189
188
  }
190
189
 
191
190
  if (onVideoApiCall) {
192
191
  onVideoApiCall({
193
192
  play: handleVideoPlayApiCall,
194
193
  pause: handleVideoPauseApiCall,
195
194
  seek: handleVideoSeekApiCall,
196
195
  })
197
196
  }
198
197
  return () => {
199
198
  const dispose = disposeRef.current
200
199
  dispose && dispose()
201
200
  disposeRef.current = null
202
201
  }
203
202
  }, [])
204
203
 
205
204
  const handleMuted = useCallback(() => {
206
205
  if (!isH5 || !ref.current) return
207
206
  const handleMutedState = ref.current.muted
208
207
  if (handleMutedState === true) {
209
208
  ref.current.muted = false
210
209
  setVideoMutedState(false)
211
210
  } else {
212
211
  ref.current.muted = true
213
212
  setVideoMutedState(true)
214
213
  }
215
214
  }, [videoMutedState])
216
215
 
217
216
  const handleVideoInViewCallback = useCallback(() => {
218
217
  if (!isH5 || !ref.current) return
219
218
  console.log(
220
219
  `
221
220
  )} CustomVideo handleVideoInViewCallback id:${id} 进入可视区域 lastPlayStatusRef.current:${lastPlayStatusRef.current},paused:${ref.current.paused}`,
222
221
  )
223
222
  isInViewStateRef.current = true
224
223
  if (
225
224
  autoplay &&
226
225
  ((mockAutoplay && !initPlayStatusRef.current) ||
227
226
  lastPlayStatusRef.current === -1) &&
228
227
  ref.current.paused
229
228
  ) {
230
229
  console.log(`CustomVideo id:${id} 首次进入可视区域`)
231
230
  playVideo(PlayVideoType.FIRST)
232
231
  } else if (lastPlayStatusRef.current === 1 && ref.current.paused) {
233
232
  console.log(`CustomVideo id:${id} 非首次进入可视区域`)
234
233
  playVideo()
235
234
  }
236
235
  typeof inViewCallback === 'function' && inViewCallback()
237
236
  }, [])
238
237
 
239
238
  const handleVideoOutViewCallback = useCallback(() => {
240
239
  if (!isH5 || !ref.current) return
241
240
  isInViewStateRef.current = false
242
241
  console.log(
243
242
  `CustomVideo handleVideoOutViewCallback id:${id} 不在可视区域,视频暂停,lastPlayStatusRef:${lastPlayStatusRef.current}`,
244
243
  )
245
244
  pauseVideo()
246
245
  typeof outViewCallback === 'function' && outViewCallback()
247
246
  }, [])
248
247
 
249
248
  const getVideoWidthAndHeightStyle = () => {
250
249
  const style = {}
251
250
  width && (style['width'] = width)
252
251
  height && (style['height'] = height)
253
252
  return style
254
253
  }
255
254
 
256
255
  const getMuteBtnBackgroundImageStyle = useCallback(() => {
257
256
  const isMutedPicSrc = muteBtnPicSrcObj?.IS_MUTED
258
257
  const notMutedPicSrc = muteBtnPicSrcObj?.NOT_MUTED
259
258
  const finalIsMutedPicSrc =
260
259
  typeof isMutedPicSrc !== 'undefined' && isMutedPicSrc !== ''
261
260
  ? isMutedPicSrc
262
261
  : DEFAULT_MUTE_BTN_PIC.IS_MUTED
263
262
  const finalNotMutedPicSrc =
264
263
  typeof notMutedPicSrc !== 'undefined' && notMutedPicSrc !== ''
265
264
  ? notMutedPicSrc
266
265
  : DEFAULT_MUTE_BTN_PIC.NOT_MUTED
267
266
  return {
268
267
  backgroundImage: `url(${
269
268
  videoMutedState ? finalIsMutedPicSrc : finalNotMutedPicSrc
270
269
  })`,
271
270
  }
272
271
  }, [videoMutedState])
273
272
  return src ? (
274
273
  <InOrOutViewObserver
275
274
  inViewCallback={handleVideoInViewCallback}
276
275
  outViewCallback={handleVideoOutViewCallback}
277
276
  threshold={threshold}
278
277
  >
279
278
  {isH5 ? (
280
279
  <View
281
280
  className={customVideoStyle['d-video-wrap']}
282
281
  style={{ ...style, ...getVideoWidthAndHeightStyle() }}
283
282
  >
284
283
  <video
285
284
  style={{ ...videoStyle }}
286
285
  className={classNames(customVideoStyle['d-video-play'], {
287
286
  'd-video-forbid-fullscreen-button': isSystemVideo,
288
287
  })}
289
288
  id={id}
290
289
  data-jd-video={true}
291
290
  src={src}
292
291
  controls={controls}
293
292
  poster={poster ? addHttps(poster) : ''}
294
293
  ref={ref}
295
294
  loop={loop}
296
295
  autoPlay={autoplay}
297
296
  muted={MUTED}
298
297
  x5-playsinline="true"
299
298
  playsInline
300
299
  webkit-playsinline="true"
301
300
  controlsList={
302
301
  isH5AndJdShopView
303
302
  ? 'nodownload nofullscreen noremoteplayback'
304
303
  : ''
305
304
  }
306
305
  onError={e => {
307
306
  const errMsg = formatVedioErrorMsg(e.target?.error)
308
307
  const data = {
309
308
  type: 'video',
310
309
  subType: 'CustomVideo',
311
310
  isSystemVideo,
312
311
  src,
313
312
  autoplay,
314
313
  errMsg,
315
314
  isH5,
316
315
  }
317
316
  console.log('CustomVideo error 1:', data)
318
317
  draBusinessCustomReport(data)
319
318
  }}
320
319
  onPlay={e => {
321
320
  lastPlayStatusRef.current = 1
322
321
  onPlayCallback && onPlayCallback(e)
323
322
  }}
324
323
  onPause={e => {
325
324
  if (isInViewStateRef.current) {
326
325
  lastPlayStatusRef.current = 0
327
326
  }
328
327
  onPauseCallback && onPauseCallback(e)
329
328
  }}
330
329
  />
331
330
  {!controls && showMuteBtn && (
332
331
  <View
333
332
  className={classNames(
334
333
  customVideoStyle['d-video-mute-btn'],
335
334
  customVideoStyle[`d-mute-btn-${muteButtonPostion}`],
336
335
  `${muteBtnClassName}`,
337
336
  )}
338
337
  style={{ ...getMuteBtnBackgroundImageStyle(), ...muteBtnStyle }}
339
338
  onClick={handleMuted}
340
339
  ></View>
341
340
  )}
342
341
  </View>
343
342
  ) : (
344
343
  <Video
345
344
  style={{ ...videoStyle }}
346
345
  ref={ref}
347
346
  className={customVideoStyle['d-video-play']}
348
347
  src={src}
349
348
  id={id}
350
349
  controls={controls}
351
350
  poster={poster ? addHttps(poster) : ''}
352
351
  loop={loop}
353
352
  data-jd-video={true}
354
353
  autoplay={autoplay}
355
354
  muted={MUTED}
356
355
  showMuteBtn={showMuteBtn}
357
356
  showFullscreenBtn={showFullscreenBtn}
358
357
  objectFit={objectFit}
359
358
  onError={e => {
360
359
  const errMsg = formatVedioErrorMsg(e.target?.error)
361
360
  const data = {
362
361
  type: 'video',
363
362
  subType: 'CustomVideo',
364
363
  isSystemVideo,
365
364
  src,
366
365
  autoplay,
367
366
  errMsg,
368
367
  isH5,
369
368
  }
370
369
  console.log('CustomVideo error 2:', data)
371
370
  draBusinessCustomReport(data)
372
371
  }}
373
372
  onPlay={e => {
374
373
  lastPlayStatusRef.current = 1
375
374
  onPlayCallback && onPlayCallback(e)
376
375
  }}
377
376
  onPause={e => {
378
377
  if (isInViewStateRef.current) {
379
378
  lastPlayStatusRef.current = 0
380
379
  }
381
380
  onPauseCallback && onPauseCallback(e)
382
381
  }}
383
382
  />
384
383
  )}
385
384
  </InOrOutViewObserver>
386
385
  ) : null
387
386
  },
388
387
  return process.env.BUILD_TYPE !== BUILD_TYPE.DECORATE
389
388
  isSystemVideo: false,
390
389
  id: '',
391
390
  style: {},
392
391
  videoStyle: {},
393
392
  className: '',
394
393
  src: '',
395
394
  width: '100%',
396
395
  height: '100%',
397
396
  controls: false,
398
397
  poster: '',
399
398
  autoplay: true,
400
399
  mockAutoplay: getDefaultMockAutoplay(),
401
400
  loop: true,
402
401
  showMuteBtn: true,
403
402
  muteButtonPostion: 'topLeft',
404
403
  muteBtnPicSrcObj: DEFAULT_MUTE_BTN_PIC,
405
404
  muteBtnClassName: '',
406
405
  muteBtnStyle: {},
407
406
  showFullscreenBtn: false,
408
407
  objectFit: 'cover',
409
408
  threshold: 0.6,
409
+ import Taro from '@tarojs/taro';
410
410
  isH5,
411
411
  addHttps,
412
412
  isH5AndJdShopView,
413
413
  draBusinessCustomReport,
414
414
  isJdAndIosDevice,
415
415
  const {
416
416
  isSystemVideo,
417
417
  floorData,
418
418
  style,
419
419
  videoStyle,
420
420
  src,
421
421
  width,
422
422
  height,
423
423
  controls,
424
424
  id,
425
425
  poster,
426
426
  autoplay: isvAutoplay,
427
427
  loop,
428
428
  showMuteBtn: isvShowMuteBtn,
429
429
  muteButtonPostion,
430
430
  showFullscreenBtn,
431
431
  muteBtnPicSrcObj,
432
432
  muteBtnClassName,
433
433
  muteBtnStyle,
434
434
  objectFit,
435
435
  mockAutoplay,
436
436
  threshold = 0.6,
437
437
  onPlayCallback,
438
438
  onPauseCallback,
439
439
  onVideoApiCall,
440
440
  inViewCallback,
441
441
  outViewCallback,
442
442
  } = props;
443
443
  const { wifiVideoAutoPlay } = global.info.sysInfo;
444
444
  const isFollowAppVideoPlayStatus = global.getDynamicConfig('isFollowAppVideoPlayStatus');
445
445
  let showMuteBtn = isvShowMuteBtn;
446
446
  let autoplay = isvAutoplay;
447
447
  if (isSystemVideo) {
448
448
  showMuteBtn = false;
449
449
  autoplay = wifiVideoAutoPlay;
450
450
  } else {
451
451
  if (isvAutoplay && isFollowAppVideoPlayStatus) {
452
452
  autoplay = wifiVideoAutoPlay;
453
453
  }
454
454
  }
455
455
  console.log(
456
456
  'CustomVideo',
457
457
  'isSystemVideo:',
458
458
  isSystemVideo,
459
459
  'wifiVideoAutoPlay:',
460
460
  wifiVideoAutoPlay,
461
461
  ',isvAutoplay:',
462
462
  isvAutoplay,
463
463
  ',isFollowAppVideoPlayStatus:',
464
464
  isFollowAppVideoPlayStatus,
465
465
  ',autoplay:',
466
466
  autoplay,
467
467
  ',id:',
468
468
  id,
469
469
  );
470
470
  const [videoMutedState, setVideoMutedState] = useState(MUTED);
471
471
  const lastPlayStatusRef = useRef(-1);
472
472
  const manualPauseStateRef = useRef(false);
473
473
  const initPlayStatusRef = useRef(false);
474
474
  const isInViewStateRef = useRef(false);
475
475
  const disposeRef = useRef<Function | null>();
476
476
  const initFloorIndexRef = useRef(-1);
477
477
  ref === null && (ref = useRef<HTMLVideoElement | null>());
478
478
 
479
479
  const playVideo = useCallback(() => {
480
480
  if (ref && ref.current) {
481
481
  console.log(`CustomVideo id:${id} 开始播放视频`);
482
482
  const result = ref.current.play();
483
483
  result &&
484
484
  result
485
485
  .then(() => {
486
486
  console.log(`播放视频成功`);
487
487
  })
488
488
  .catch((e) => {
489
489
  console.log('CustomVideo playVideo ', e.name, ':', e.message);
490
490
  });
491
491
  }
492
492
  }, []);
493
493
 
494
494
  const pauseVideo = useCallback(() => {
495
495
  if (ref && ref.current) {
496
496
  console.log(`CustomVideo id:${id} 暂停视频`);
497
497
  ref.current.pause();
498
498
  }
499
499
  }, []);
500
500
 
501
501
  const handleIosFirstScreenVideoPause = useCallback(() => {
502
502
  const floorIndex = initFloorIndexRef.current;
503
503
  if (ref.current && floorIndex >= 0 && floorIndex < 4) {
504
504
  ref.current.setAttribute('data-init-pause', true);
505
505
  if (!ref.current.paused) {
506
506
  ref.current.pause();
507
507
  } else {
508
508
  setTimeout(() => {
509
509
  !ref.current.paused && ref.current.pause();
510
510
  }, 1500);
511
511
  }
512
512
  }
513
513
  }, []);
514
514
 
515
515
  useEffect(() => {
516
516
  isJdAndIosDevice &&
517
517
  autoplay &&
518
518
  mockAutoplay &&
519
519
  Taro.eventCenter.on(TaroEventType.PAGE_DOCUMENT_VISIBILITY_CHANGE_INIT_NOW_TIME, (res) => {
520
520
  console.log('app初始化可见性变化=>', res, '如果是0,表示不可见');
521
521
  res === 0 && handleIosFirstScreenVideoPause();
522
522
  });
523
523
  }, []);
524
524
 
525
525
  useEffect(() => {
526
526
  if (!isH5 || !ref.current) return;
527
527
  if (floorData && floorData.hasOwnProperty('containerIndex')) {
528
528
  initFloorIndexRef.current = floorData.containerIndex;
529
529
  } else {
530
530
  const containerNode = ref.current.closest('[data-container-id]');
531
531
  if (containerNode) {
532
532
  initFloorIndexRef.current = Number(containerNode.getAttribute('data-container-index'));
533
533
  }
534
534
  }
535
535
  if (autoplay && mockAutoplay) {
536
536
 
537
537
  const callInitAutoplay = () => {
538
538
  console.log(`CustomVideo id:${id} 触发初始化autoplay callInitAutoplay`);
539
539
  if (
540
540
  autoplay &&
541
541
  mockAutoplay &&
542
542
  !initPlayStatusRef.current &&
543
543
  isInViewStateRef.current &&
544
544
  ref.current.paused
545
545
  ) {
546
546
  playVideo();
547
547
  }
548
548
  };
549
549
  const onWeixinJSBridgeReady = () => {
550
550
  callInitAutoplay();
551
551
  };
552
552
  const onTouchstart = () => {
553
553
  callInitAutoplay();
554
554
  };
555
555
  const onScroll = () => {
556
556
  callInitAutoplay();
557
557
  };
558
558
  const onPlay = () => {
559
559
  if (!initPlayStatusRef.current) {
560
560
  const dispose = disposeRef.current;
561
561
  dispose && dispose();
562
562
  disposeRef.current = null;
563
563
  }
564
564
  initPlayStatusRef.current = true;
565
565
  };
566
566
  document?.addEventListener('WeixinJSBridgeReady', onWeixinJSBridgeReady);
567
567
  document?.addEventListener('touchstart', onTouchstart);
568
568
  document?.addEventListener('scroll', onScroll);
569
569
  ref.current.addEventListener('play', onPlay);
570
570
  const dispose = () => {
571
571
  console.log('调用dispose');
572
572
  document?.removeEventListener('WeixinJSBridgeReady', onWeixinJSBridgeReady);
573
573
  document?.removeEventListener('touchstart', onTouchstart);
574
574
  document?.removeEventListener('scroll', onScroll);
575
575
  ref?.current?.removeEventListener('play', onPlay);
576
576
  };
577
577
  disposeRef.current = dispose;
578
578
  }
579
579
  const handleVideoPlayApiCall = () => {
580
580
  if (!isH5 || !ref.current) return;
581
581
  playVideo();
582
582
  manualPauseStateRef.current = false;
583
583
  };
584
584
  const handleVideoPauseApiCall = () => {
585
585
  if (!isH5 || !ref.current) return;
586
586
  manualPauseStateRef.current = true;
587
587
  pauseVideo();
588
588
  };
589
589
 
590
590
  const handleVideoSeekApiCall = (position: number) => {
591
591
  if (!isH5 || !ref.current) return;
592
592
  if (typeof position === 'undefined' || typeof position !== 'number') return;
593
593
  ref.current.currentTime = position;
594
594
  };
595
595
 
596
596
  if (onVideoApiCall) {
597
597
  onVideoApiCall({
598
598
  play: handleVideoPlayApiCall,
599
599
  pause: handleVideoPauseApiCall,
600
600
  seek: handleVideoSeekApiCall,
601
601
  });
602
602
  }
603
603
  return () => {
604
604
  const dispose = disposeRef.current;
605
605
  dispose && dispose();
606
606
  disposeRef.current = null;
607
607
  };
608
608
  }, []);
609
609
 
610
610
  const handleMuted = useCallback(() => {
611
611
  if (!isH5 || !ref.current) return;
612
612
  const handleMutedState = ref.current.muted;
613
613
  if (handleMutedState === true) {
614
614
  ref.current.muted = false;
615
615
  setVideoMutedState(false);
616
616
  } else {
617
617
  ref.current.muted = true;
618
618
  setVideoMutedState(true);
619
619
  }
620
620
  }, [videoMutedState]);
621
621
 
622
622
  const handleVideoInViewCallback = useCallback(() => {
623
623
  if (!isH5 || !ref.current) return;
624
624
  console.log(
625
625
  `
626
626
  )} CustomVideo handleVideoInViewCallback id:${id} 进入可视区域 lastPlayStatusRef.current:${lastPlayStatusRef.current},paused:${ref.current.paused}`,
627
627
  );
628
628
  isInViewStateRef.current = true;
629
629
  if (
630
630
  autoplay &&
631
631
  ((mockAutoplay && !initPlayStatusRef.current) || lastPlayStatusRef.current === -1) &&
632
632
  ref.current.paused
633
633
  ) {
634
634
  console.log(`CustomVideo id:${id} 首次进入可视区域`);
635
635
  playVideo();
636
636
  } else if (lastPlayStatusRef.current === 1 && ref.current.paused) {
637
637
  console.log(`CustomVideo id:${id} 非首次进入可视区域`);
638
638
  playVideo();
639
639
  }
640
640
  typeof inViewCallback === 'function' && inViewCallback();
641
641
  }, []);
642
642
 
643
643
  const handleVideoOutViewCallback = useCallback(() => {
644
644
  if (!isH5 || !ref.current) return;
645
645
  isInViewStateRef.current = false;
646
646
  console.log(
647
647
  `CustomVideo handleVideoOutViewCallback id:${id} 不在可视区域,视频暂停,lastPlayStatusRef:${lastPlayStatusRef.current}`,
648
648
  );
649
649
  pauseVideo();
650
650
  typeof outViewCallback === 'function' && outViewCallback();
651
651
  }, []);
652
652
 
653
653
  const getVideoWidthAndHeightStyle = () => {
654
654
  const style = {};
655
655
  width && (style['width'] = width);
656
656
  height && (style['height'] = height);
657
657
  return style;
658
658
  };
659
659
 
660
660
  const getMuteBtnBackgroundImageStyle = useCallback(() => {
661
661
  const isMutedPicSrc = muteBtnPicSrcObj?.IS_MUTED;
662
662
  const notMutedPicSrc = muteBtnPicSrcObj?.NOT_MUTED;
663
663
  const finalIsMutedPicSrc =
664
664
  typeof isMutedPicSrc !== 'undefined' && isMutedPicSrc !== ''
665
665
  ? isMutedPicSrc
666
666
  : DEFAULT_MUTE_BTN_PIC.IS_MUTED;
667
667
  const finalNotMutedPicSrc =
668
668
  typeof notMutedPicSrc !== 'undefined' && notMutedPicSrc !== ''
669
669
  ? notMutedPicSrc
670
670
  : DEFAULT_MUTE_BTN_PIC.NOT_MUTED;
671
671
  return {
672
672
  backgroundImage: `url(${videoMutedState ? finalIsMutedPicSrc : finalNotMutedPicSrc})`,
673
673
  };
674
674
  }, [videoMutedState]);
675
675
  return src ? (
676
676
  <InOrOutViewObserver
677
677
  inViewCallback={handleVideoInViewCallback}
678
678
  outViewCallback={handleVideoOutViewCallback}
679
679
  threshold={threshold}
680
680
  >
681
681
  {isH5 ? (
682
682
  <View
683
683
  className={customVideoStyle['d-video-wrap']}
684
684
  style={{ ...style, ...getVideoWidthAndHeightStyle() }}
685
685
  >
686
686
  <video
687
687
  style={{ ...videoStyle }}
688
688
  className={classNames(customVideoStyle['d-video-play'], {
689
689
  'd-video-forbid-fullscreen-button': isSystemVideo,
690
690
  })}
691
691
  id={id}
692
692
  data-jd-video={true}
693
693
  src={src}
694
694
  controls={controls}
695
695
  poster={poster ? addHttps(poster) : ''}
696
696
  ref={ref}
697
697
  loop={loop}
698
698
  autoPlay={autoplay}
699
699
  muted={MUTED}
700
700
  x5-playsinline="true"
701
701
  playsInline
702
702
  webkit-playsinline="true"
703
703
  controlsList={isH5AndJdShopView ? 'nodownload nofullscreen noremoteplayback' : ''}
704
704
  onError={(e) => {
705
705
  const errMsg = formatVedioErrorMsg(e.target?.error);
706
706
  const data = {
707
707
  type: 'video',
708
708
  subType: 'CustomVideo',
709
709
  isSystemVideo,
710
710
  src,
711
711
  autoplay,
712
712
  errMsg,
713
713
  isH5,
714
714
  };
715
715
  console.log('CustomVideo error 1:', data);
716
716
  draBusinessCustomReport(data);
717
717
  }}
718
718
  onPlay={(e) => {
719
719
  lastPlayStatusRef.current = 1;
720
720
  onPlayCallback && onPlayCallback(e);
721
721
  }}
722
722
  onPause={(e) => {
723
723
  if (isInViewStateRef.current) {
724
724
  lastPlayStatusRef.current = 0;
725
725
  }
726
726
  onPauseCallback && onPauseCallback(e);
727
727
  }}
728
728
  />
729
729
  {!controls && showMuteBtn && (
730
730
  <View
731
731
  className={classNames(
732
732
  customVideoStyle['d-video-mute-btn'],
733
733
  customVideoStyle[`d-mute-btn-${muteButtonPostion}`],
734
734
  `${muteBtnClassName}`,
735
735
  )}
736
736
  style={{ ...getMuteBtnBackgroundImageStyle(), ...muteBtnStyle }}
737
737
  onClick={handleMuted}
738
738
  ></View>
739
739
  )}
740
740
  </View>
741
741
  ) : (
742
742
  <Video
743
743
  style={{ ...videoStyle }}
744
744
  ref={ref}
745
745
  className={customVideoStyle['d-video-play']}
746
746
  src={src}
747
747
  id={id}
748
748
  controls={controls}
749
749
  poster={poster ? addHttps(poster) : ''}
750
750
  loop={loop}
751
751
  data-jd-video={true}
752
752
  autoplay={autoplay}
753
753
  muted={MUTED}
754
754
  showMuteBtn={showMuteBtn}
755
755
  showFullscreenBtn={showFullscreenBtn}
756
756
  objectFit={objectFit}
757
757
  onError={(e) => {
758
758
  const errMsg = formatVedioErrorMsg(e.target?.error);
759
759
  const data = {
760
760
  type: 'video',
761
761
  subType: 'CustomVideo',
762
762
  isSystemVideo,
763
763
  src,
764
764
  autoplay,
765
765
  errMsg,
766
766
  isH5,
767
767
  };
768
768
  console.log('CustomVideo error 2:', data);
769
769
  draBusinessCustomReport(data);
770
770
  }}
771
771
  onPlay={(e) => {
772
772
  lastPlayStatusRef.current = 1;
773
773
  onPlayCallback && onPlayCallback(e);
774
774
  }}
775
775
  onPause={(e) => {
776
776
  if (isInViewStateRef.current) {
777
777
  lastPlayStatusRef.current = 0;
778
778
  }
779
779
  onPauseCallback && onPauseCallback(e);
780
780
  }}
781
781
  />
782
782
  )}
783
783
  </InOrOutViewObserver>
784
784
  ) : null;
785
785
  return process.env.BUILD_TYPE !== BUILD_TYPE.DECORATE;
786
786
  isSystemVideo: false,
787
787
  id: '',
788
788
  style: {},
789
789
  videoStyle: {},
790
790
  className: '',
791
791
  src: '',
792
792
  width: '100%',
793
793
  height: '100%',
794
794
  controls: false,
795
795
  poster: '',
796
796
  autoplay: true,
797
797
  mockAutoplay: getDefaultMockAutoplay(),
798
798
  loop: true,
799
799
  showMuteBtn: true,
800
800
  muteButtonPostion: 'topLeft',
801
801
  muteBtnPicSrcObj: DEFAULT_MUTE_BTN_PIC,
802
802
  muteBtnClassName: '',
803
803
  muteBtnStyle: {},
804
804
  showFullscreenBtn: false,
805
805
  objectFit: 'cover',
806
806
  threshold: 0.6,