unified-video-framework 1.4.1 → 1.4.3
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.
- package/package.json +1 -1
- package/packages/ios/README.md +84 -0
- package/packages/web/dist/WebPlayer.d.ts.map +1 -1
- package/packages/web/dist/WebPlayer.js +390 -9
- package/packages/web/dist/WebPlayer.js.map +1 -1
- package/packages/web/dist/paywall/PaywallController.d.ts +24 -0
- package/packages/web/dist/react/WebPlayerView.d.ts +22 -0
- package/packages/web/dist/react/WebPlayerView.d.ts.map +1 -1
- package/packages/web/dist/react/WebPlayerView.js +109 -1
- package/packages/web/dist/react/WebPlayerView.js.map +1 -1
- package/packages/web/src/WebPlayer.ts +394 -10
- package/packages/web/src/react/WebPlayerView.tsx +169 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unified-video-framework",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.3",
|
|
4
4
|
"description": "Cross-platform video player framework supporting iOS, Android, Web, Smart TVs (Samsung/LG), Roku, and more",
|
|
5
5
|
"main": "packages/core/dist/index.js",
|
|
6
6
|
"types": "packages/core/dist/index.d.ts",
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# UnifiedVideoPlayer (iOS SDK)
|
|
2
|
+
|
|
3
|
+
A unified iOS video player SDK with:
|
|
4
|
+
- HLS playback (AVPlayer)
|
|
5
|
+
- FairPlay DRM (SPC/CKC)
|
|
6
|
+
- Subtitles/audio track selection (AVMediaSelection)
|
|
7
|
+
- Picture-in-Picture (AVPictureInPictureController)
|
|
8
|
+
- AirPlay (AVRoutePickerView)
|
|
9
|
+
- Remote Command Center + Now Playing (lock screen controls)
|
|
10
|
+
- Background audio (AVAudioSession)
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
### CocoaPods
|
|
15
|
+
1) Ensure this SDK is in a public Git repository. Update the podspec `s.source` to point at that repo and tag.
|
|
16
|
+
2) In your Podfile:
|
|
17
|
+
```ruby
|
|
18
|
+
platform :ios, '13.0'
|
|
19
|
+
use_frameworks!
|
|
20
|
+
|
|
21
|
+
target 'YourApp' do
|
|
22
|
+
pod 'UnifiedVideoPlayer', :git => 'https://github.com/yourcompany/unified-video-ios.git', :tag => '1.0.0'
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
3) Run:
|
|
26
|
+
```bash
|
|
27
|
+
pod install
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Swift Package Manager
|
|
31
|
+
Add the package at the repository URL or use Add Local Package pointing to `packages/ios`.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
```swift
|
|
35
|
+
import UnifiedVideoPlayer
|
|
36
|
+
|
|
37
|
+
let containerView = UIView(frame: .zero)
|
|
38
|
+
let player = UnifiedVideoPlayer()
|
|
39
|
+
let config = PlayerConfiguration()
|
|
40
|
+
config.autoPlay = true
|
|
41
|
+
|
|
42
|
+
player.initialize(container: containerView, configuration: config)
|
|
43
|
+
|
|
44
|
+
let source = MediaSource(url: "https://example.com/stream.m3u8")
|
|
45
|
+
source.metadata = ["title": "Demo Stream"]
|
|
46
|
+
player.onReady = { print("ready") }
|
|
47
|
+
player.onQualityChange = { br in print("bitrate: \(br)") }
|
|
48
|
+
|
|
49
|
+
player.load(source: source)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### FairPlay DRM
|
|
53
|
+
```swift
|
|
54
|
+
let drm = DRMConfiguration(type: "fairplay", licenseUrl: "https://license.example.com/fps")
|
|
55
|
+
drm.certificateUrl = "https://license.example.com/cert"
|
|
56
|
+
drm.headers = ["X-Tenant-ID": "default"]
|
|
57
|
+
|
|
58
|
+
let source = MediaSource(url: "https://cdn.example.com/protected/playlist.m3u8")
|
|
59
|
+
source.drm = drm
|
|
60
|
+
player.load(source: source)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Tracks
|
|
64
|
+
```swift
|
|
65
|
+
let audios = player.audioTracks() // [String]
|
|
66
|
+
let subs = player.subtitleTracks() // [String]
|
|
67
|
+
player.selectAudioTrack(index: 0)
|
|
68
|
+
player.selectSubtitleTrack(index: -1) // off
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### PiP & AirPlay
|
|
72
|
+
```swift
|
|
73
|
+
player.startPictureInPicture()
|
|
74
|
+
player.stopPictureInPicture()
|
|
75
|
+
let airPlay = player.makeAirPlayPickerView()
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Capabilities
|
|
79
|
+
- Enable Background Modes > Audio
|
|
80
|
+
- For DRM endpoints, configure ATS exceptions if necessary.
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
MIT
|
|
84
|
+
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebPlayer.d.ts","sourceRoot":"","sources":["../src/WebPlayer.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"WebPlayer.d.ts","sourceRoot":"","sources":["../src/WebPlayer.ts"],"names":[],"mappings":"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"}
|
|
@@ -641,6 +641,32 @@ class WebPlayer extends core_1.BasePlayer {
|
|
|
641
641
|
--uvf-firefox-scrollbar-color: rgba(255,255,255,0.25);
|
|
642
642
|
}
|
|
643
643
|
|
|
644
|
+
/* Responsive Container Styles */
|
|
645
|
+
.uvf-responsive-container {
|
|
646
|
+
width: 100%;
|
|
647
|
+
margin: 0 auto;
|
|
648
|
+
box-sizing: border-box;
|
|
649
|
+
display: block;
|
|
650
|
+
position: relative;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
.uvf-responsive-container .uvf-player-wrapper {
|
|
654
|
+
width: 100%;
|
|
655
|
+
height: 100%;
|
|
656
|
+
max-width: inherit;
|
|
657
|
+
max-height: inherit;
|
|
658
|
+
box-sizing: border-box;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.uvf-responsive-container .uvf-video-container {
|
|
662
|
+
width: 100%;
|
|
663
|
+
height: 100%;
|
|
664
|
+
position: relative;
|
|
665
|
+
background: radial-gradient(ellipse at center, #1a1a2e 0%, #000 100%);
|
|
666
|
+
overflow: hidden;
|
|
667
|
+
box-sizing: border-box;
|
|
668
|
+
}
|
|
669
|
+
|
|
644
670
|
/* Gradient border effect */
|
|
645
671
|
.uvf-player-wrapper::before {
|
|
646
672
|
content: '';
|
|
@@ -921,6 +947,19 @@ class WebPlayer extends core_1.BasePlayer {
|
|
|
921
947
|
pointer-events: none;
|
|
922
948
|
}
|
|
923
949
|
|
|
950
|
+
/* Skip button specific styles for consistency */
|
|
951
|
+
#uvf-skip-back svg,
|
|
952
|
+
#uvf-skip-forward svg {
|
|
953
|
+
width: 22px;
|
|
954
|
+
height: 22px;
|
|
955
|
+
stroke-width: 0;
|
|
956
|
+
transform: scale(1);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
#uvf-skip-forward svg {
|
|
960
|
+
transform: scale(1) scaleX(-1); /* Mirror the icon for forward */
|
|
961
|
+
}
|
|
962
|
+
|
|
924
963
|
.uvf-control-btn.play-pause {
|
|
925
964
|
width: 50px;
|
|
926
965
|
height: 50px;
|
|
@@ -1405,6 +1444,318 @@ class WebPlayer extends core_1.BasePlayer {
|
|
|
1405
1444
|
transform: translateY(-10px) !important;
|
|
1406
1445
|
pointer-events: none;
|
|
1407
1446
|
}
|
|
1447
|
+
|
|
1448
|
+
/* Fullscreen specific styles */
|
|
1449
|
+
.uvf-player-wrapper.uvf-fullscreen .uvf-video-container {
|
|
1450
|
+
width: 100vw;
|
|
1451
|
+
height: 100vh;
|
|
1452
|
+
max-width: none;
|
|
1453
|
+
max-height: none;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
/* Ensure overlays remain visible in fullscreen */
|
|
1457
|
+
.uvf-player-wrapper.uvf-fullscreen .uvf-title-bar,
|
|
1458
|
+
.uvf-player-wrapper.uvf-fullscreen .uvf-top-controls,
|
|
1459
|
+
.uvf-player-wrapper.uvf-fullscreen .uvf-controls-bar,
|
|
1460
|
+
.uvf-player-wrapper.uvf-fullscreen .uvf-top-gradient,
|
|
1461
|
+
.uvf-player-wrapper.uvf-fullscreen .uvf-controls-gradient {
|
|
1462
|
+
z-index: 2147483647; /* Maximum z-index value */
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
.uvf-player-wrapper.uvf-fullscreen:hover .uvf-title-bar,
|
|
1466
|
+
.uvf-player-wrapper.uvf-fullscreen:hover .uvf-top-controls,
|
|
1467
|
+
.uvf-player-wrapper.uvf-fullscreen.controls-visible .uvf-title-bar,
|
|
1468
|
+
.uvf-player-wrapper.uvf-fullscreen.controls-visible .uvf-top-controls {
|
|
1469
|
+
opacity: 1;
|
|
1470
|
+
transform: translateY(0);
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
/* Responsive Media Queries */
|
|
1474
|
+
/* Mobile devices (portrait) */
|
|
1475
|
+
@media screen and (max-width: 767px) and (orientation: portrait) {
|
|
1476
|
+
.uvf-responsive-container {
|
|
1477
|
+
padding: 0;
|
|
1478
|
+
width: 100vw !important;
|
|
1479
|
+
margin: 0;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
.uvf-responsive-container .uvf-player-wrapper {
|
|
1483
|
+
width: 100vw !important;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
.uvf-responsive-container .uvf-video-container {
|
|
1487
|
+
width: 100vw !important;
|
|
1488
|
+
aspect-ratio: unset !important; /* Let JS handle the aspect ratio */
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
.uvf-controls-bar {
|
|
1492
|
+
padding: 12px 8px;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
.uvf-controls-row {
|
|
1496
|
+
gap: 6px;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
.uvf-control-btn {
|
|
1500
|
+
width: 34px;
|
|
1501
|
+
height: 34px;
|
|
1502
|
+
min-width: 34px;
|
|
1503
|
+
min-height: 34px;
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
.uvf-control-btn.play-pause {
|
|
1507
|
+
width: 42px;
|
|
1508
|
+
height: 42px;
|
|
1509
|
+
min-width: 42px;
|
|
1510
|
+
min-height: 42px;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
.uvf-time-display {
|
|
1514
|
+
font-size: 11px;
|
|
1515
|
+
min-width: 70px;
|
|
1516
|
+
padding: 0 4px;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
.uvf-top-controls {
|
|
1520
|
+
top: 8px;
|
|
1521
|
+
right: 8px;
|
|
1522
|
+
gap: 6px;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
.uvf-top-btn {
|
|
1526
|
+
width: 34px;
|
|
1527
|
+
height: 34px;
|
|
1528
|
+
min-width: 34px;
|
|
1529
|
+
min-height: 34px;
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
.uvf-title-bar {
|
|
1533
|
+
padding: 8px;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
.uvf-video-title {
|
|
1537
|
+
font-size: 15px;
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
.uvf-video-subtitle {
|
|
1541
|
+
font-size: 11px;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
.uvf-center-play-btn {
|
|
1545
|
+
width: 56px;
|
|
1546
|
+
height: 56px;
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
.uvf-center-play-btn svg {
|
|
1550
|
+
width: 26px;
|
|
1551
|
+
height: 26px;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
.uvf-progress-bar-wrapper {
|
|
1555
|
+
height: 8px;
|
|
1556
|
+
margin-bottom: 10px;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
.uvf-progress-handle {
|
|
1560
|
+
width: 16px;
|
|
1561
|
+
height: 16px;
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
.uvf-settings-menu {
|
|
1565
|
+
min-width: 150px;
|
|
1566
|
+
bottom: 35px;
|
|
1567
|
+
right: 5px;
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
/* Mobile devices (landscape) */
|
|
1572
|
+
@media screen and (max-width: 767px) and (orientation: landscape) {
|
|
1573
|
+
.uvf-responsive-container {
|
|
1574
|
+
width: 100vw !important;
|
|
1575
|
+
height: 100vh !important;
|
|
1576
|
+
margin: 0;
|
|
1577
|
+
padding: 0;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
.uvf-responsive-container .uvf-player-wrapper {
|
|
1581
|
+
width: 100vw !important;
|
|
1582
|
+
height: 100vh !important;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
.uvf-responsive-container .uvf-video-container {
|
|
1586
|
+
width: 100vw !important;
|
|
1587
|
+
height: 100vh !important;
|
|
1588
|
+
aspect-ratio: unset !important;
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
.uvf-controls-bar {
|
|
1592
|
+
padding: 8px;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
.uvf-top-controls {
|
|
1596
|
+
top: 6px;
|
|
1597
|
+
right: 6px;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
.uvf-title-bar {
|
|
1601
|
+
padding: 6px;
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
.uvf-control-btn {
|
|
1605
|
+
width: 32px;
|
|
1606
|
+
height: 32px;
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
.uvf-control-btn.play-pause {
|
|
1610
|
+
width: 40px;
|
|
1611
|
+
height: 40px;
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
/* Tablet devices */
|
|
1616
|
+
@media screen and (min-width: 768px) and (max-width: 1023px) {
|
|
1617
|
+
.uvf-controls-bar {
|
|
1618
|
+
padding: 18px 15px;
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
.uvf-control-btn {
|
|
1622
|
+
width: 42px;
|
|
1623
|
+
height: 42px;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
.uvf-control-btn.play-pause {
|
|
1627
|
+
width: 48px;
|
|
1628
|
+
height: 48px;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
.uvf-top-controls {
|
|
1632
|
+
top: 15px;
|
|
1633
|
+
right: 15px;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
.uvf-title-bar {
|
|
1637
|
+
padding: 15px;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
.uvf-center-play-btn {
|
|
1641
|
+
width: 70px;
|
|
1642
|
+
height: 70px;
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
/* Large screens */
|
|
1647
|
+
@media screen and (min-width: 1024px) {
|
|
1648
|
+
.uvf-responsive-container {
|
|
1649
|
+
padding: 10px;
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
/* Touch device optimizations */
|
|
1654
|
+
@media (hover: none) and (pointer: coarse) {
|
|
1655
|
+
.uvf-control-btn {
|
|
1656
|
+
min-width: 44px;
|
|
1657
|
+
min-height: 44px;
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
.uvf-top-btn {
|
|
1661
|
+
min-width: 44px;
|
|
1662
|
+
min-height: 44px;
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
.uvf-progress-bar-wrapper {
|
|
1666
|
+
height: 8px;
|
|
1667
|
+
cursor: pointer;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
.uvf-progress-handle {
|
|
1671
|
+
width: 20px;
|
|
1672
|
+
height: 20px;
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
.uvf-volume-slider {
|
|
1676
|
+
height: 10px;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
/* Paywall Responsive Styles */
|
|
1681
|
+
.uvf-paywall-overlay {
|
|
1682
|
+
position: absolute !important;
|
|
1683
|
+
inset: 0 !important;
|
|
1684
|
+
background: rgba(0,0,0,0.9) !important;
|
|
1685
|
+
z-index: 2147483000 !important;
|
|
1686
|
+
display: none !important;
|
|
1687
|
+
align-items: center !important;
|
|
1688
|
+
justify-content: center !important;
|
|
1689
|
+
padding: 10px !important;
|
|
1690
|
+
box-sizing: border-box !important;
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
.uvf-paywall-modal {
|
|
1694
|
+
width: 90vw !important;
|
|
1695
|
+
height: auto !important;
|
|
1696
|
+
max-width: 500px !important;
|
|
1697
|
+
max-height: 90vh !important;
|
|
1698
|
+
background: #0f0f10 !important;
|
|
1699
|
+
border: 1px solid rgba(255,255,255,0.15) !important;
|
|
1700
|
+
border-radius: 12px !important;
|
|
1701
|
+
display: flex !important;
|
|
1702
|
+
flex-direction: column !important;
|
|
1703
|
+
overflow: auto !important;
|
|
1704
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.7) !important;
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
/* Paywall Mobile Portrait */
|
|
1708
|
+
@media screen and (max-width: 767px) and (orientation: portrait) {
|
|
1709
|
+
.uvf-paywall-modal {
|
|
1710
|
+
width: 95vw !important;
|
|
1711
|
+
max-width: none !important;
|
|
1712
|
+
max-height: 85vh !important;
|
|
1713
|
+
margin: 0 !important;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
.uvf-paywall-modal > div:first-child {
|
|
1717
|
+
padding: 12px 16px !important;
|
|
1718
|
+
font-size: 16px !important;
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
.uvf-paywall-modal > div:last-child {
|
|
1722
|
+
padding: 16px !important;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
/* Paywall Mobile Landscape */
|
|
1727
|
+
@media screen and (max-width: 767px) and (orientation: landscape) {
|
|
1728
|
+
.uvf-paywall-modal {
|
|
1729
|
+
width: 85vw !important;
|
|
1730
|
+
max-height: 80vh !important;
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
.uvf-paywall-modal > div:first-child {
|
|
1734
|
+
padding: 10px 16px !important;
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
.uvf-paywall-modal > div:last-child {
|
|
1738
|
+
padding: 14px !important;
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
/* Paywall Tablet */
|
|
1743
|
+
@media screen and (min-width: 768px) and (max-width: 1023px) {
|
|
1744
|
+
.uvf-paywall-modal {
|
|
1745
|
+
width: 80vw !important;
|
|
1746
|
+
max-width: 600px !important;
|
|
1747
|
+
max-height: 80vh !important;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
/* Paywall Desktop */
|
|
1752
|
+
@media screen and (min-width: 1024px) {
|
|
1753
|
+
.uvf-paywall-modal {
|
|
1754
|
+
width: 70vw !important;
|
|
1755
|
+
max-width: 800px !important;
|
|
1756
|
+
max-height: 70vh !important;
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1408
1759
|
`;
|
|
1409
1760
|
}
|
|
1410
1761
|
createCustomControls(container) {
|
|
@@ -1440,11 +1791,6 @@ class WebPlayer extends core_1.BasePlayer {
|
|
|
1440
1791
|
</svg>
|
|
1441
1792
|
<span>Stop Casting</span>
|
|
1442
1793
|
</button>
|
|
1443
|
-
<div class="uvf-top-btn" id="uvf-playlist-btn" title="Add to Playlist">
|
|
1444
|
-
<svg viewBox="0 0 24 24">
|
|
1445
|
-
<path d="M14 10H2v2h12v-2zm0-4H2v2h12V6zm4 8v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM2 16h8v-2H2v2z"/>
|
|
1446
|
-
</svg>
|
|
1447
|
-
</div>
|
|
1448
1794
|
<div class="uvf-top-btn" id="uvf-share-btn" title="Share">
|
|
1449
1795
|
<svg viewBox="0 0 24 24">
|
|
1450
1796
|
<path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z"/>
|
|
@@ -1498,12 +1844,16 @@ class WebPlayer extends core_1.BasePlayer {
|
|
|
1498
1844
|
const skipBackBtn = document.createElement('button');
|
|
1499
1845
|
skipBackBtn.className = 'uvf-control-btn';
|
|
1500
1846
|
skipBackBtn.id = 'uvf-skip-back';
|
|
1501
|
-
skipBackBtn.
|
|
1847
|
+
skipBackBtn.setAttribute('title', 'Skip backward 10s');
|
|
1848
|
+
skipBackBtn.setAttribute('aria-label', 'Skip backward 10 seconds');
|
|
1849
|
+
skipBackBtn.innerHTML = '<svg viewBox="0 0 24 24"><path d="M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z"/></svg>';
|
|
1502
1850
|
controlsRow.appendChild(skipBackBtn);
|
|
1503
1851
|
const skipForwardBtn = document.createElement('button');
|
|
1504
1852
|
skipForwardBtn.className = 'uvf-control-btn';
|
|
1505
1853
|
skipForwardBtn.id = 'uvf-skip-forward';
|
|
1506
|
-
skipForwardBtn.
|
|
1854
|
+
skipForwardBtn.setAttribute('title', 'Skip forward 10s');
|
|
1855
|
+
skipForwardBtn.setAttribute('aria-label', 'Skip forward 10 seconds');
|
|
1856
|
+
skipForwardBtn.innerHTML = '<svg viewBox="0 0 24 24"><path d="M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z"/></svg>';
|
|
1507
1857
|
controlsRow.appendChild(skipForwardBtn);
|
|
1508
1858
|
const volumeControl = document.createElement('div');
|
|
1509
1859
|
volumeControl.className = 'uvf-volume-control';
|
|
@@ -1746,6 +2096,39 @@ class WebPlayer extends core_1.BasePlayer {
|
|
|
1746
2096
|
this.exitFullscreen();
|
|
1747
2097
|
}
|
|
1748
2098
|
});
|
|
2099
|
+
document.addEventListener('fullscreenchange', () => {
|
|
2100
|
+
const wrapper = this.playerWrapper || this.container?.querySelector('.uvf-player-wrapper');
|
|
2101
|
+
if (wrapper) {
|
|
2102
|
+
if (document.fullscreenElement) {
|
|
2103
|
+
wrapper.classList.add('uvf-fullscreen');
|
|
2104
|
+
}
|
|
2105
|
+
else {
|
|
2106
|
+
wrapper.classList.remove('uvf-fullscreen');
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
const fullscreenBtn = document.getElementById('uvf-fullscreen-btn');
|
|
2110
|
+
if (fullscreenBtn) {
|
|
2111
|
+
fullscreenBtn.innerHTML = document.fullscreenElement
|
|
2112
|
+
? '<svg viewBox="0 0 24 24"><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/></svg>'
|
|
2113
|
+
: '<svg viewBox="0 0 24 24"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>';
|
|
2114
|
+
}
|
|
2115
|
+
});
|
|
2116
|
+
['webkitfullscreenchange', 'mozfullscreenchange'].forEach(eventName => {
|
|
2117
|
+
document.addEventListener(eventName, () => {
|
|
2118
|
+
const wrapper = this.playerWrapper || this.container?.querySelector('.uvf-player-wrapper');
|
|
2119
|
+
if (wrapper) {
|
|
2120
|
+
const isFullscreen = !!(document.fullscreenElement ||
|
|
2121
|
+
document.webkitFullscreenElement ||
|
|
2122
|
+
document.mozFullScreenElement);
|
|
2123
|
+
if (isFullscreen) {
|
|
2124
|
+
wrapper.classList.add('uvf-fullscreen');
|
|
2125
|
+
}
|
|
2126
|
+
else {
|
|
2127
|
+
wrapper.classList.remove('uvf-fullscreen');
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
});
|
|
2131
|
+
});
|
|
1749
2132
|
this.video.addEventListener('waiting', () => {
|
|
1750
2133
|
const loading = document.getElementById('uvf-loading');
|
|
1751
2134
|
if (loading)
|
|
@@ -1800,11 +2183,9 @@ class WebPlayer extends core_1.BasePlayer {
|
|
|
1800
2183
|
pipBtn?.addEventListener('click', () => this.togglePiP());
|
|
1801
2184
|
const castBtn = document.getElementById('uvf-cast-btn');
|
|
1802
2185
|
const stopCastBtn = document.getElementById('uvf-stop-cast-btn');
|
|
1803
|
-
const playlistBtn = document.getElementById('uvf-playlist-btn');
|
|
1804
2186
|
const shareBtn = document.getElementById('uvf-share-btn');
|
|
1805
2187
|
castBtn?.addEventListener('click', () => this.onCastButtonClick());
|
|
1806
2188
|
stopCastBtn?.addEventListener('click', () => this.stopCasting());
|
|
1807
|
-
playlistBtn?.addEventListener('click', () => this.showNotification('Added to playlist'));
|
|
1808
2189
|
shareBtn?.addEventListener('click', () => this.shareVideo());
|
|
1809
2190
|
document.addEventListener('click', (e) => {
|
|
1810
2191
|
if (!e.target.closest('#uvf-settings-btn') &&
|