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

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