stormcloud-video-player 0.8.22 → 0.8.24

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/lib/index.js CHANGED
@@ -1555,300 +1555,759 @@ function disconnectMQTT() {
1555
1555
  status = "disconnected";
1556
1556
  }
1557
1557
  }
1558
- // src/utils/tracking.ts
1559
- var cachedBrowserId = null;
1560
- function getClientInfo() {
1561
- var _screen, _screen1, _screen2, _screen3, _screen_orientation, _screen4, _screen5, _window, _window1, _window_screen_orientation, _window_screen, _navigator_languages;
1558
+ // src/utils/vastEnvironmentSignals.ts
1559
+ var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
1560
+ var AIRY_WEBOS_APP_ID = "com.freeairytv.webos";
1561
+ var AIRY_TIZEN_APP_ID = "com.freeairytv.samsung";
1562
+ var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
1563
+ var AIRY_APP_NAME = "AiryTV Movies & TV";
1564
+ var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
1565
+ var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
1566
+ var PLAYER_ID_STORAGE_KEY = "stormcloud.player.id";
1567
+ var LG_TEST_APP_ID = "com.hulu.plus";
1568
+ var LG_TEST_APP_NAME = "Hulu";
1569
+ var LG_TEST_CONTENT_URL = "https://www.hulu.com/live-tv";
1570
+ var _lgTestDeviceId;
1571
+ function getLgTestDeviceId() {
1572
+ if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();
1573
+ return _lgTestDeviceId;
1574
+ }
1575
+ function isLgWebOS() {
1576
+ if (typeof navigator === "undefined") return false;
1577
+ return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);
1578
+ }
1579
+ function getDefaultAppId() {
1580
+ if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
1562
1581
  var ua = navigator.userAgent;
1563
- var platform = navigator.platform;
1564
- var vendor = navigator.vendor || "";
1565
- var maxTouchPoints = navigator.maxTouchPoints || 0;
1566
- var memory = navigator.deviceMemory || null;
1567
- var hardwareConcurrency = navigator.hardwareConcurrency || 1;
1568
- var screenInfo = {
1569
- width: (_screen = screen) === null || _screen === void 0 ? void 0 : _screen.width,
1570
- height: (_screen1 = screen) === null || _screen1 === void 0 ? void 0 : _screen1.height,
1571
- availWidth: (_screen2 = screen) === null || _screen2 === void 0 ? void 0 : _screen2.availWidth,
1572
- availHeight: (_screen3 = screen) === null || _screen3 === void 0 ? void 0 : _screen3.availHeight,
1573
- orientation: ((_screen4 = screen) === null || _screen4 === void 0 ? void 0 : (_screen_orientation = _screen4.orientation) === null || _screen_orientation === void 0 ? void 0 : _screen_orientation.type) || "",
1574
- pixelDepth: (_screen5 = screen) === null || _screen5 === void 0 ? void 0 : _screen5.pixelDepth
1575
- };
1576
- var deviceType = "desktop";
1577
- var brand = "Unknown";
1578
- var os = "Unknown";
1579
- var model = "";
1580
- var isSmartTV = false;
1581
- var isAndroid = false;
1582
- var isWebView = false;
1583
- var isWebApp = false;
1584
- if (ua.includes("Web0S")) {
1585
- brand = "LG";
1586
- os = "webOS";
1587
- isSmartTV = true;
1588
- deviceType = "tv";
1589
- var webosMatch = ua.match(/Web0S\/([^\s]+)/);
1590
- model = webosMatch ? "webOS ".concat(webosMatch[1]) : "webOS TV";
1591
- } else if (ua.includes("Tizen")) {
1592
- brand = "Samsung";
1593
- os = "Tizen";
1594
- isSmartTV = true;
1595
- deviceType = "tv";
1596
- var tizenMatch = ua.match(/Tizen\/([^\s]+)/);
1597
- var tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? "Smart TV" : "";
1598
- model = tizenMatch ? "Tizen ".concat(tizenMatch[1], " ").concat(tvMatch).trim() : "Tizen TV";
1599
- } else if (ua.includes("Philips")) {
1600
- brand = "Philips";
1601
- os = "Saphi";
1602
- isSmartTV = true;
1603
- deviceType = "tv";
1604
- } else if (ua.includes("Sharp") || ua.includes("AQUOS")) {
1605
- brand = "Sharp";
1606
- os = "Android TV";
1607
- isSmartTV = true;
1608
- deviceType = "tv";
1609
- } else if (ua.includes("Android") && (ua.includes("Sony") || vendor.includes("Sony"))) {
1610
- brand = "Sony";
1611
- os = "Android TV";
1612
- isSmartTV = true;
1613
- deviceType = "tv";
1614
- } else if (ua.includes("Android") && (ua.includes("NetCast") || ua.includes("LG"))) {
1615
- brand = "LG";
1616
- os = "Android TV";
1617
- isSmartTV = true;
1618
- deviceType = "tv";
1619
- } else if (ua.includes(" Roku") || ua.includes("Roku/")) {
1620
- brand = "Roku";
1621
- os = "Roku OS";
1622
- isSmartTV = true;
1623
- deviceType = "tv";
1624
- } else if (ua.includes("AppleTV")) {
1625
- brand = "Apple";
1626
- os = "tvOS";
1627
- isSmartTV = true;
1628
- deviceType = "tv";
1582
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;
1583
+ if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;
1584
+ if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;
1585
+ return AIRY_ANDROID_APP_ID;
1586
+ }
1587
+ var DEVICE_ID_STORAGE_KEYS = [
1588
+ "rdid",
1589
+ "ifa",
1590
+ "advertisingId",
1591
+ "advertising_id",
1592
+ "deviceAdvertisingId",
1593
+ "aaid",
1594
+ "adid",
1595
+ "rida",
1596
+ "tifa",
1597
+ "lgudid"
1598
+ ];
1599
+ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
1600
+ "aaid",
1601
+ "adid"
1602
+ ]);
1603
+ function resolveVastEnvironmentSignals(isCtv) {
1604
+ var _ref;
1605
+ var bridgeSignals = readNativeBridgeSignals();
1606
+ var platformDevice = readPlatformNativeDeviceId();
1607
+ var lg = isCtv && isLgWebOS();
1608
+ var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId || (lg && platformDevice.limitAdTracking !== true ? getLgTestDeviceId() : void 0);
1609
+ var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType() || (lg ? "lgudid" : void 0);
1610
+ var platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
1611
+ var limitAdTracking = deviceId != null ? (_ref = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false : void 0;
1612
+ if (isCtv) {
1613
+ return _object_spread_props(_object_spread({
1614
+ isCtv: true,
1615
+ contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),
1616
+ appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || (lg ? LG_TEST_APP_ID : getDefaultAppId()),
1617
+ appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),
1618
+ sessionId: getOrCreateCtvSessionId()
1619
+ }, deviceId ? {
1620
+ deviceId: deviceId
1621
+ } : {}, deviceIdType ? {
1622
+ deviceIdType: deviceIdType
1623
+ } : {}, limitAdTracking != null ? {
1624
+ limitAdTracking: limitAdTracking
1625
+ } : {}), {
1626
+ deviceTypeHint: 5
1627
+ });
1629
1628
  }
1630
- if (ua.includes("Android")) {
1631
- isAndroid = true;
1632
- os = "Android";
1633
- deviceType = /Mobile/.test(ua) ? "mobile" : "tablet";
1634
- if (ua.includes("Android") && (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi"))) {
1635
- deviceType = "tv";
1636
- isSmartTV = true;
1637
- brand = brand === "Unknown" ? "Android TV" : brand;
1638
- }
1639
- var androidModelMatch = ua.match(/\(([^)]*Android[^)]*)\)/);
1640
- if (androidModelMatch && androidModelMatch[1]) {
1641
- model = androidModelMatch[1];
1642
- }
1629
+ return _object_spread({
1630
+ isCtv: false
1631
+ }, deviceId ? {
1632
+ deviceId: deviceId
1633
+ } : {}, deviceIdType ? {
1634
+ deviceIdType: deviceIdType
1635
+ } : {}, limitAdTracking != null ? {
1636
+ limitAdTracking: limitAdTracking
1637
+ } : {});
1638
+ }
1639
+ function inferDeviceIdType() {
1640
+ if (typeof navigator === "undefined") {
1641
+ return void 0;
1643
1642
  }
1644
- if (/iPad|iPhone|iPod/.test(ua)) {
1645
- os = "iOS";
1646
- deviceType = "mobile";
1647
- brand = "Apple";
1648
- if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {
1649
- deviceType = "tablet";
1650
- }
1643
+ var ua = navigator.userAgent;
1644
+ if (/Roku/i.test(ua)) return "rida";
1645
+ if (/Tizen|Samsung/i.test(ua)) return "tifa";
1646
+ if (/AppleTV|Apple TV/i.test(ua)) return "tvOS";
1647
+ if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
1648
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return "lgudid";
1649
+ if (/Android|Google TV/i.test(ua)) return "aaid";
1650
+ if (/iPhone|iPad|iPod/i.test(ua)) return "idfa";
1651
+ return void 0;
1652
+ }
1653
+ function isEquivalentDeviceIdType(tagType, runtimeType) {
1654
+ if (!tagType || !runtimeType) return false;
1655
+ var tag = tagType.toLowerCase();
1656
+ var runtime = runtimeType.toLowerCase();
1657
+ if (tag === runtime) return true;
1658
+ return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
1659
+ }
1660
+ function resolveNativeDeviceId() {
1661
+ var bridgeSignals = readNativeBridgeSignals();
1662
+ var platformDevice = readPlatformNativeDeviceId();
1663
+ var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId;
1664
+ if (!deviceId || isMacroPlaceholder(deviceId) || isZeroedAdId(deviceId)) {
1665
+ return void 0;
1651
1666
  }
1652
- if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {
1653
- if (ua.includes("Windows")) {
1654
- os = "Windows";
1655
- deviceType = "desktop";
1656
- } else if (ua.includes("Mac") && !/iPhone/.test(ua)) {
1657
- os = "macOS";
1658
- deviceType = "desktop";
1659
- if (maxTouchPoints > 1) deviceType = "tablet";
1660
- } else if (ua.includes("Linux")) {
1661
- os = "Linux";
1662
- deviceType = "desktop";
1663
- }
1667
+ return deviceId;
1668
+ }
1669
+ function getOrCreateStoredUuid(storageKey) {
1670
+ if (typeof window === "undefined") {
1671
+ return void 0;
1664
1672
  }
1665
- if (brand === "Unknown") {
1666
- if (vendor.includes("Google") || ua.includes("Chrome")) brand = "Google";
1667
- if (vendor.includes("Apple")) brand = "Apple";
1668
- if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
1673
+ var existing = readStoredString(storageKey);
1674
+ if (existing) {
1675
+ return existing;
1669
1676
  }
1670
- isWebView = /wv|WebView|Linux; U;/.test(ua);
1671
- if (((_window = window) === null || _window === void 0 ? void 0 : _window.outerHeight) === 0 && ((_window1 = window) === null || _window1 === void 0 ? void 0 : _window1.outerWidth) === 0) {
1672
- isWebView = true;
1677
+ var id = createUuid();
1678
+ try {
1679
+ var _window_localStorage;
1680
+ (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(storageKey, id);
1681
+ } catch (unused) {}
1682
+ return id;
1683
+ }
1684
+ function getOrCreateCtvSessionId() {
1685
+ var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
1686
+ if (existing) {
1687
+ return existing;
1673
1688
  }
1674
- isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || ((_window_screen = window.screen) === null || _window_screen === void 0 ? void 0 : (_window_screen_orientation = _window_screen.orientation) === null || _window_screen_orientation === void 0 ? void 0 : _window_screen_orientation.angle) !== void 0;
1675
- return {
1676
- brand: brand,
1677
- os: os,
1678
- model: model || ua.substring(0, 50) + "...",
1679
- deviceType: deviceType,
1680
- isSmartTV: isSmartTV,
1681
- isAndroid: isAndroid,
1682
- isWebView: isWebView,
1683
- isWebApp: isWebApp,
1684
- domain: window.location.hostname,
1685
- origin: window.location.origin,
1686
- path: window.location.pathname,
1687
- userAgent: ua,
1688
- vendor: vendor,
1689
- platform: platform,
1690
- screen: screenInfo,
1691
- hardwareConcurrency: hardwareConcurrency,
1692
- deviceMemory: memory,
1693
- maxTouchPoints: maxTouchPoints,
1694
- language: navigator.language,
1695
- languages: ((_navigator_languages = navigator.languages) === null || _navigator_languages === void 0 ? void 0 : _navigator_languages.join(",")) || "",
1696
- cookieEnabled: navigator.cookieEnabled,
1697
- doNotTrack: navigator.doNotTrack || "",
1698
- referrer: document.referrer,
1699
- visibilityState: document.visibilityState
1700
- };
1689
+ var sessionId = createUuid();
1690
+ try {
1691
+ var _window_localStorage;
1692
+ (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
1693
+ } catch (unused) {}
1694
+ return sessionId;
1701
1695
  }
1702
- function getBrowserID(clientInfo) {
1703
- return _async_to_generator(function() {
1704
- var _crypto_subtle, fingerprintString, encodedData, utf8, buffer, i, hashBuffer, hashHex, unused, hash, i1, char, fallbackHash, timestamp, random;
1705
- return _ts_generator(this, function(_state) {
1706
- switch(_state.label){
1707
- case 0:
1708
- if (cachedBrowserId) {
1709
- return [
1710
- 2,
1711
- cachedBrowserId
1712
- ];
1713
- }
1714
- fingerprintString = JSON.stringify(clientInfo);
1715
- if (!(typeof crypto !== "undefined" && ((_crypto_subtle = crypto.subtle) === null || _crypto_subtle === void 0 ? void 0 : _crypto_subtle.digest))) return [
1716
- 3,
1717
- 5
1718
- ];
1719
- _state.label = 1;
1720
- case 1:
1721
- _state.trys.push([
1722
- 1,
1723
- 4,
1724
- ,
1725
- 5
1726
- ]);
1727
- return [
1728
- 4,
1729
- crypto.subtle.digest("SHA-256", new Uint8Array([
1730
- 1,
1731
- 2,
1732
- 3
1733
- ]))
1734
- ];
1735
- case 2:
1736
- _state.sent();
1737
- if (typeof TextEncoder !== "undefined") {
1738
- encodedData = new TextEncoder().encode(fingerprintString);
1739
- } else {
1740
- utf8 = unescape(encodeURIComponent(fingerprintString));
1741
- buffer = new Uint8Array(utf8.length);
1742
- for(i = 0; i < utf8.length; i++){
1743
- buffer[i] = utf8.charCodeAt(i);
1744
- }
1745
- encodedData = buffer;
1746
- }
1747
- return [
1748
- 4,
1749
- crypto.subtle.digest("SHA-256", encodedData)
1750
- ];
1751
- case 3:
1752
- hashBuffer = _state.sent();
1753
- hashHex = Array.from(new Uint8Array(hashBuffer)).map(function(b) {
1754
- return b.toString(16).padStart(2, "0");
1755
- }).join("");
1756
- cachedBrowserId = hashHex;
1757
- return [
1758
- 2,
1759
- hashHex
1760
- ];
1761
- case 4:
1762
- unused = _state.sent();
1763
- console.warn("[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash");
1764
- return [
1765
- 3,
1766
- 5
1767
- ];
1768
- case 5:
1769
- hash = 0;
1770
- for(i1 = 0; i1 < fingerprintString.length; i1++){
1771
- char = fingerprintString.charCodeAt(i1);
1772
- hash = (hash << 5) - hash + char;
1773
- hash = hash & hash;
1774
- }
1775
- fallbackHash = Math.abs(hash).toString(16).padStart(8, "0");
1776
- timestamp = Date.now().toString(16).padStart(12, "0");
1777
- random = Math.random().toString(16).substring(2, 14).padStart(12, "0");
1778
- cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, "0");
1779
- return [
1780
- 2,
1781
- cachedBrowserId
1782
- ];
1696
+ function createUuid() {
1697
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
1698
+ return crypto.randomUUID();
1699
+ }
1700
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
1701
+ var value = Math.floor(Math.random() * 16);
1702
+ var nibble = char === "x" ? value : value & 3 | 8;
1703
+ return nibble.toString(16);
1704
+ });
1705
+ }
1706
+ function readPlatformNativeDeviceId() {
1707
+ if (typeof window === "undefined") return {};
1708
+ try {
1709
+ var _window_webapis;
1710
+ var adinfo = (_window_webapis = window.webapis) === null || _window_webapis === void 0 ? void 0 : _window_webapis.adinfo;
1711
+ if (adinfo) {
1712
+ var tifa = typeof adinfo.getTIFA === "function" ? adinfo.getTIFA() : adinfo.tifa;
1713
+ if (typeof tifa === "string" && tifa && !isMacroPlaceholder(tifa)) {
1714
+ var lat = typeof adinfo.isLATEnabled === "function" ? adinfo.isLATEnabled() : void 0;
1715
+ return _object_spread({
1716
+ deviceId: tifa,
1717
+ deviceIdType: "tifa"
1718
+ }, typeof lat === "boolean" ? {
1719
+ limitAdTracking: lat
1720
+ } : {});
1783
1721
  }
1784
- });
1785
- })();
1722
+ }
1723
+ } catch (unused) {}
1724
+ try {
1725
+ var webOSDev = window.webOSDev;
1726
+ if (webOSDev) {
1727
+ var _webOSDev_lgudid;
1728
+ var lgudid = typeof webOSDev.LGUDID === "function" ? webOSDev.LGUDID() : (_webOSDev_lgudid = webOSDev.lgudid) !== null && _webOSDev_lgudid !== void 0 ? _webOSDev_lgudid : webOSDev.LGUDID;
1729
+ if (typeof lgudid === "string" && lgudid) {
1730
+ if (isZeroedAdId(lgudid)) {
1731
+ return {
1732
+ deviceIdType: "lgudid",
1733
+ limitAdTracking: true
1734
+ };
1735
+ }
1736
+ if (!isMacroPlaceholder(lgudid)) {
1737
+ return {
1738
+ deviceId: lgudid,
1739
+ deviceIdType: "lgudid",
1740
+ limitAdTracking: false
1741
+ };
1742
+ }
1743
+ }
1744
+ }
1745
+ } catch (unused) {}
1746
+ try {
1747
+ var roku = window.Roku;
1748
+ if (roku) {
1749
+ var rida = typeof roku.getPublisherUniqueId === "function" ? roku.getPublisherUniqueId() : roku.rida;
1750
+ if (typeof rida === "string" && rida && !isMacroPlaceholder(rida)) {
1751
+ return {
1752
+ deviceId: rida,
1753
+ deviceIdType: "rida",
1754
+ limitAdTracking: false
1755
+ };
1756
+ }
1757
+ }
1758
+ } catch (unused) {}
1759
+ return {};
1786
1760
  }
1787
- function canPublish(licenseKey) {
1788
- return Boolean(isMQTTEnabled() && licenseKey);
1761
+ var ZEROED_AD_ID_PATTERNS = /* @__PURE__ */ new Set([
1762
+ "38400000-8cf0-11bd-b23e-10b96e40000d",
1763
+ "00000000-0000-0000-0000-000000000000"
1764
+ ]);
1765
+ function isMacroPlaceholder(value) {
1766
+ var t = value.trim();
1767
+ return !t || /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/.test(t) || /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(t) || ZEROED_AD_ID_PATTERNS.has(t.toLowerCase());
1789
1768
  }
1790
- function buildPlayerMetricEvent() {
1791
- return _async_to_generator(function() {
1792
- var context, flags, _flags_captureAt, _flags_adLoaded, _flags_adDetect, clientInfo, playerId, captureAt;
1793
- var _arguments = arguments;
1794
- return _ts_generator(this, function(_state) {
1795
- switch(_state.label){
1796
- case 0:
1797
- context = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {}, flags = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
1798
- clientInfo = getClientInfo();
1799
- return [
1800
- 4,
1801
- getBrowserID(clientInfo)
1802
- ];
1803
- case 1:
1804
- playerId = _state.sent();
1805
- captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
1806
- return [
1807
- 2,
1808
- _object_spread({
1809
- player_id: playerId,
1810
- device_type: clientInfo.deviceType,
1811
- os: clientInfo.os.toLowerCase(),
1812
- ad_loaded: (_flags_adLoaded = flags.adLoaded) !== null && _flags_adLoaded !== void 0 ? _flags_adLoaded : false,
1813
- ad_detect: (_flags_adDetect = flags.adDetect) !== null && _flags_adDetect !== void 0 ? _flags_adDetect : false,
1814
- capture_at: captureAt
1815
- }, context.inputStreamType ? {
1816
- input_stream_type: context.inputStreamType
1817
- } : {})
1818
- ];
1769
+ function isZeroedAdId(value) {
1770
+ return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());
1771
+ }
1772
+ function readNativeBridgeSignals() {
1773
+ if (typeof window === "undefined") {
1774
+ return {};
1775
+ }
1776
+ var candidates = [
1777
+ window.__STORMCLOUD_CTV_AD_INFO__,
1778
+ window.__STORMCLOUD_CTV__,
1779
+ window.stormcloudCtv,
1780
+ window.AiryTV,
1781
+ window.Android,
1782
+ window.webOS,
1783
+ window.tizen,
1784
+ window.amazon
1785
+ ].filter(Boolean);
1786
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1787
+ try {
1788
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1789
+ var source = _step.value;
1790
+ var contentUrl = readBridgeValue(source, [
1791
+ "contentUrl",
1792
+ "url",
1793
+ "videoUrl",
1794
+ "canonicalUrl"
1795
+ ]) || void 0;
1796
+ var appId = readBridgeValue(source, [
1797
+ "appId",
1798
+ "msid",
1799
+ "applicationId",
1800
+ "packageName"
1801
+ ]) || void 0;
1802
+ var appName = readBridgeValue(source, [
1803
+ "appName",
1804
+ "an",
1805
+ "applicationName"
1806
+ ]) || void 0;
1807
+ var deviceId = readBridgeValue(source, [
1808
+ "rdid",
1809
+ "ifa",
1810
+ "advertisingId",
1811
+ "adId",
1812
+ "deviceId",
1813
+ "lgudid",
1814
+ "LGUDID",
1815
+ "tifa",
1816
+ "rida",
1817
+ "afai",
1818
+ "aaid"
1819
+ ]) || void 0;
1820
+ if (!contentUrl && !deviceId && !appId && !appName) continue;
1821
+ var deviceIdType = readBridgeValue(source, [
1822
+ "idtype",
1823
+ "deviceIdType",
1824
+ "advertisingIdType",
1825
+ "idType"
1826
+ ]) || inferDeviceIdType();
1827
+ var limitAdTracking = readBridgeBoolean(source, [
1828
+ "is_lat",
1829
+ "limitAdTracking",
1830
+ "limitedAdTracking",
1831
+ "lat"
1832
+ ]);
1833
+ return _object_spread({}, contentUrl ? {
1834
+ contentUrl: contentUrl
1835
+ } : {}, appId ? {
1836
+ appId: appId
1837
+ } : {}, appName ? {
1838
+ appName: appName
1839
+ } : {}, deviceId ? {
1840
+ deviceId: deviceId
1841
+ } : {}, deviceId && deviceIdType ? {
1842
+ deviceIdType: deviceIdType
1843
+ } : {}, deviceId && limitAdTracking != null ? {
1844
+ limitAdTracking: limitAdTracking
1845
+ } : {});
1846
+ }
1847
+ } catch (err) {
1848
+ _didIteratorError = true;
1849
+ _iteratorError = err;
1850
+ } finally{
1851
+ try {
1852
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1853
+ _iterator.return();
1819
1854
  }
1820
- });
1821
- }).apply(this, arguments);
1855
+ } finally{
1856
+ if (_didIteratorError) {
1857
+ throw _iteratorError;
1858
+ }
1859
+ }
1860
+ }
1861
+ return {};
1822
1862
  }
1823
- function publishTracking(licenseKey, channel, body) {
1824
- ensureMQTTClient();
1825
- publishMQTT(buildPlayerTopic(licenseKey, channel), body);
1863
+ function readBridgeValue(source, keys) {
1864
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1865
+ try {
1866
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1867
+ var key = _step.value;
1868
+ var value = source === null || source === void 0 ? void 0 : source[key];
1869
+ if (typeof value === "string" && value) {
1870
+ return value;
1871
+ }
1872
+ if (typeof value === "function") {
1873
+ try {
1874
+ var result = value.call(source);
1875
+ if (typeof result === "string" && result) {
1876
+ return result;
1877
+ }
1878
+ } catch (unused) {}
1879
+ }
1880
+ }
1881
+ } catch (err) {
1882
+ _didIteratorError = true;
1883
+ _iteratorError = err;
1884
+ } finally{
1885
+ try {
1886
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1887
+ _iterator.return();
1888
+ }
1889
+ } finally{
1890
+ if (_didIteratorError) {
1891
+ throw _iteratorError;
1892
+ }
1893
+ }
1894
+ }
1895
+ return void 0;
1826
1896
  }
1827
- function sendInitialTracking(_0) {
1828
- return _async_to_generator(function(licenseKey) {
1829
- var context, metricEvent, error;
1830
- var _arguments = arguments;
1897
+ function readBridgeBoolean(source, keys) {
1898
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1899
+ try {
1900
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1901
+ var key = _step.value;
1902
+ var value = source === null || source === void 0 ? void 0 : source[key];
1903
+ var normalized = normalizeBoolean(value);
1904
+ if (normalized != null) {
1905
+ return normalized;
1906
+ }
1907
+ if (typeof value === "function") {
1908
+ try {
1909
+ var result = normalizeBoolean(value.call(source));
1910
+ if (result != null) {
1911
+ return result;
1912
+ }
1913
+ } catch (unused) {}
1914
+ }
1915
+ }
1916
+ } catch (err) {
1917
+ _didIteratorError = true;
1918
+ _iteratorError = err;
1919
+ } finally{
1920
+ try {
1921
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1922
+ _iterator.return();
1923
+ }
1924
+ } finally{
1925
+ if (_didIteratorError) {
1926
+ throw _iteratorError;
1927
+ }
1928
+ }
1929
+ }
1930
+ return void 0;
1931
+ }
1932
+ function readStoredDeviceId() {
1933
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1934
+ try {
1935
+ for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1936
+ var key = _step.value;
1937
+ var value = readStoredString(key);
1938
+ if (value) {
1939
+ return value;
1940
+ }
1941
+ }
1942
+ } catch (err) {
1943
+ _didIteratorError = true;
1944
+ _iteratorError = err;
1945
+ } finally{
1946
+ try {
1947
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1948
+ _iterator.return();
1949
+ }
1950
+ } finally{
1951
+ if (_didIteratorError) {
1952
+ throw _iteratorError;
1953
+ }
1954
+ }
1955
+ }
1956
+ return void 0;
1957
+ }
1958
+ function readStoredString(key) {
1959
+ if (typeof window === "undefined") {
1960
+ return void 0;
1961
+ }
1962
+ try {
1963
+ var _window_localStorage;
1964
+ var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
1965
+ return value || void 0;
1966
+ } catch (unused) {
1967
+ return void 0;
1968
+ }
1969
+ }
1970
+ function readStoredLimitAdTracking() {
1971
+ return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
1972
+ }
1973
+ function normalizeBoolean(value) {
1974
+ if (typeof value === "boolean") {
1975
+ return value;
1976
+ }
1977
+ if (typeof value === "number") {
1978
+ return value === 1;
1979
+ }
1980
+ if (typeof value === "string") {
1981
+ var normalized = value.toLowerCase();
1982
+ if (normalized === "1" || normalized === "true" || normalized === "yes") {
1983
+ return true;
1984
+ }
1985
+ if (normalized === "0" || normalized === "false" || normalized === "no") {
1986
+ return false;
1987
+ }
1988
+ }
1989
+ return void 0;
1990
+ }
1991
+ // src/utils/tracking.ts
1992
+ var cachedBrowserId = null;
1993
+ function getClientInfo() {
1994
+ var _screen, _screen1, _screen2, _screen3, _screen_orientation, _screen4, _screen5, _window, _window1, _window_screen_orientation, _window_screen, _navigator_languages;
1995
+ var ua = navigator.userAgent;
1996
+ var platform = navigator.platform;
1997
+ var vendor = navigator.vendor || "";
1998
+ var maxTouchPoints = navigator.maxTouchPoints || 0;
1999
+ var memory = navigator.deviceMemory || null;
2000
+ var hardwareConcurrency = navigator.hardwareConcurrency || 1;
2001
+ var screenInfo = {
2002
+ width: (_screen = screen) === null || _screen === void 0 ? void 0 : _screen.width,
2003
+ height: (_screen1 = screen) === null || _screen1 === void 0 ? void 0 : _screen1.height,
2004
+ availWidth: (_screen2 = screen) === null || _screen2 === void 0 ? void 0 : _screen2.availWidth,
2005
+ availHeight: (_screen3 = screen) === null || _screen3 === void 0 ? void 0 : _screen3.availHeight,
2006
+ orientation: ((_screen4 = screen) === null || _screen4 === void 0 ? void 0 : (_screen_orientation = _screen4.orientation) === null || _screen_orientation === void 0 ? void 0 : _screen_orientation.type) || "",
2007
+ pixelDepth: (_screen5 = screen) === null || _screen5 === void 0 ? void 0 : _screen5.pixelDepth
2008
+ };
2009
+ var deviceType = "desktop";
2010
+ var brand = "Unknown";
2011
+ var os = "Unknown";
2012
+ var model = "";
2013
+ var isSmartTV = false;
2014
+ var isAndroid = false;
2015
+ var isWebView = false;
2016
+ var isWebApp = false;
2017
+ if (ua.includes("Web0S")) {
2018
+ brand = "LG";
2019
+ os = "webOS";
2020
+ isSmartTV = true;
2021
+ deviceType = "tv";
2022
+ var webosMatch = ua.match(/Web0S\/([^\s]+)/);
2023
+ model = webosMatch ? "webOS ".concat(webosMatch[1]) : "webOS TV";
2024
+ } else if (ua.includes("Tizen")) {
2025
+ brand = "Samsung";
2026
+ os = "Tizen";
2027
+ isSmartTV = true;
2028
+ deviceType = "tv";
2029
+ var tizenMatch = ua.match(/Tizen\/([^\s]+)/);
2030
+ var tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? "Smart TV" : "";
2031
+ model = tizenMatch ? "Tizen ".concat(tizenMatch[1], " ").concat(tvMatch).trim() : "Tizen TV";
2032
+ } else if (ua.includes("Philips")) {
2033
+ brand = "Philips";
2034
+ os = "Saphi";
2035
+ isSmartTV = true;
2036
+ deviceType = "tv";
2037
+ } else if (ua.includes("Sharp") || ua.includes("AQUOS")) {
2038
+ brand = "Sharp";
2039
+ os = "Android TV";
2040
+ isSmartTV = true;
2041
+ deviceType = "tv";
2042
+ } else if (ua.includes("Android") && (ua.includes("Sony") || vendor.includes("Sony"))) {
2043
+ brand = "Sony";
2044
+ os = "Android TV";
2045
+ isSmartTV = true;
2046
+ deviceType = "tv";
2047
+ } else if (ua.includes("Android") && (ua.includes("NetCast") || ua.includes("LG"))) {
2048
+ brand = "LG";
2049
+ os = "Android TV";
2050
+ isSmartTV = true;
2051
+ deviceType = "tv";
2052
+ } else if (ua.includes(" Roku") || ua.includes("Roku/")) {
2053
+ brand = "Roku";
2054
+ os = "Roku OS";
2055
+ isSmartTV = true;
2056
+ deviceType = "tv";
2057
+ } else if (ua.includes("AppleTV")) {
2058
+ brand = "Apple";
2059
+ os = "tvOS";
2060
+ isSmartTV = true;
2061
+ deviceType = "tv";
2062
+ }
2063
+ if (ua.includes("Android")) {
2064
+ isAndroid = true;
2065
+ os = "Android";
2066
+ deviceType = /Mobile/.test(ua) ? "mobile" : "tablet";
2067
+ if (ua.includes("Android") && (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi"))) {
2068
+ deviceType = "tv";
2069
+ isSmartTV = true;
2070
+ brand = brand === "Unknown" ? "Android TV" : brand;
2071
+ }
2072
+ var androidModelMatch = ua.match(/\(([^)]*Android[^)]*)\)/);
2073
+ if (androidModelMatch && androidModelMatch[1]) {
2074
+ model = androidModelMatch[1];
2075
+ }
2076
+ }
2077
+ if (/iPad|iPhone|iPod/.test(ua)) {
2078
+ os = "iOS";
2079
+ deviceType = "mobile";
2080
+ brand = "Apple";
2081
+ if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {
2082
+ deviceType = "tablet";
2083
+ }
2084
+ }
2085
+ if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {
2086
+ if (ua.includes("Windows")) {
2087
+ os = "Windows";
2088
+ deviceType = "desktop";
2089
+ } else if (ua.includes("Mac") && !/iPhone/.test(ua)) {
2090
+ os = "macOS";
2091
+ deviceType = "desktop";
2092
+ if (maxTouchPoints > 1) deviceType = "tablet";
2093
+ } else if (ua.includes("Linux")) {
2094
+ os = "Linux";
2095
+ deviceType = "desktop";
2096
+ }
2097
+ }
2098
+ if (brand === "Unknown") {
2099
+ if (vendor.includes("Google") || ua.includes("Chrome")) brand = "Google";
2100
+ if (vendor.includes("Apple")) brand = "Apple";
2101
+ if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
2102
+ }
2103
+ isWebView = /wv|WebView|Linux; U;/.test(ua);
2104
+ if (((_window = window) === null || _window === void 0 ? void 0 : _window.outerHeight) === 0 && ((_window1 = window) === null || _window1 === void 0 ? void 0 : _window1.outerWidth) === 0) {
2105
+ isWebView = true;
2106
+ }
2107
+ isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || ((_window_screen = window.screen) === null || _window_screen === void 0 ? void 0 : (_window_screen_orientation = _window_screen.orientation) === null || _window_screen_orientation === void 0 ? void 0 : _window_screen_orientation.angle) !== void 0;
2108
+ return {
2109
+ brand: brand,
2110
+ os: os,
2111
+ model: model || ua.substring(0, 50) + "...",
2112
+ deviceType: deviceType,
2113
+ isSmartTV: isSmartTV,
2114
+ isAndroid: isAndroid,
2115
+ isWebView: isWebView,
2116
+ isWebApp: isWebApp,
2117
+ domain: window.location.hostname,
2118
+ origin: window.location.origin,
2119
+ path: window.location.pathname,
2120
+ userAgent: ua,
2121
+ vendor: vendor,
2122
+ platform: platform,
2123
+ screen: screenInfo,
2124
+ hardwareConcurrency: hardwareConcurrency,
2125
+ deviceMemory: memory,
2126
+ maxTouchPoints: maxTouchPoints,
2127
+ language: navigator.language,
2128
+ languages: ((_navigator_languages = navigator.languages) === null || _navigator_languages === void 0 ? void 0 : _navigator_languages.join(",")) || "",
2129
+ cookieEnabled: navigator.cookieEnabled,
2130
+ doNotTrack: navigator.doNotTrack || "",
2131
+ referrer: document.referrer,
2132
+ visibilityState: document.visibilityState
2133
+ };
2134
+ }
2135
+ function sha256Hex(input) {
2136
+ return _async_to_generator(function() {
2137
+ var _crypto_subtle, encodedData, utf8, buffer, i, hashBuffer, unused, hash, i1, char, fallbackHash, timestamp, random;
1831
2138
  return _ts_generator(this, function(_state) {
1832
2139
  switch(_state.label){
1833
2140
  case 0:
1834
- context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
1835
- if (!canPublish(licenseKey)) return [
1836
- 2
2141
+ if (!(typeof crypto !== "undefined" && ((_crypto_subtle = crypto.subtle) === null || _crypto_subtle === void 0 ? void 0 : _crypto_subtle.digest))) return [
2142
+ 3,
2143
+ 5
1837
2144
  ];
1838
2145
  _state.label = 1;
1839
2146
  case 1:
1840
2147
  _state.trys.push([
1841
2148
  1,
1842
- 3,
2149
+ 4,
1843
2150
  ,
1844
- 4
2151
+ 5
1845
2152
  ]);
1846
2153
  return [
1847
2154
  4,
1848
- buildPlayerMetricEvent(context, {
1849
- adLoaded: false,
1850
- adDetect: false
1851
- })
2155
+ crypto.subtle.digest("SHA-256", new Uint8Array([
2156
+ 1,
2157
+ 2,
2158
+ 3
2159
+ ]))
2160
+ ];
2161
+ case 2:
2162
+ _state.sent();
2163
+ if (typeof TextEncoder !== "undefined") {
2164
+ encodedData = new TextEncoder().encode(input);
2165
+ } else {
2166
+ utf8 = unescape(encodeURIComponent(input));
2167
+ buffer = new Uint8Array(utf8.length);
2168
+ for(i = 0; i < utf8.length; i++){
2169
+ buffer[i] = utf8.charCodeAt(i);
2170
+ }
2171
+ encodedData = buffer;
2172
+ }
2173
+ return [
2174
+ 4,
2175
+ crypto.subtle.digest("SHA-256", encodedData)
2176
+ ];
2177
+ case 3:
2178
+ hashBuffer = _state.sent();
2179
+ return [
2180
+ 2,
2181
+ Array.from(new Uint8Array(hashBuffer)).map(function(b) {
2182
+ return b.toString(16).padStart(2, "0");
2183
+ }).join("")
2184
+ ];
2185
+ case 4:
2186
+ unused = _state.sent();
2187
+ console.warn("[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash");
2188
+ return [
2189
+ 3,
2190
+ 5
2191
+ ];
2192
+ case 5:
2193
+ hash = 0;
2194
+ for(i1 = 0; i1 < input.length; i1++){
2195
+ char = input.charCodeAt(i1);
2196
+ hash = (hash << 5) - hash + char;
2197
+ hash = hash & hash;
2198
+ }
2199
+ fallbackHash = Math.abs(hash).toString(16).padStart(8, "0");
2200
+ timestamp = Date.now().toString(16).padStart(12, "0");
2201
+ random = Math.random().toString(16).substring(2, 14).padStart(12, "0");
2202
+ return [
2203
+ 2,
2204
+ (fallbackHash + timestamp + random).padEnd(64, "0")
2205
+ ];
2206
+ }
2207
+ });
2208
+ })();
2209
+ }
2210
+ function resolvePlayerIdentitySeed(clientInfo) {
2211
+ var nativeDeviceId = resolveNativeDeviceId();
2212
+ if (nativeDeviceId) {
2213
+ return "device:".concat(nativeDeviceId);
2214
+ }
2215
+ var persistedId = getOrCreateStoredUuid(PLAYER_ID_STORAGE_KEY);
2216
+ if (persistedId) {
2217
+ return "persisted:".concat(persistedId);
2218
+ }
2219
+ return "fingerprint:".concat(JSON.stringify(clientInfo));
2220
+ }
2221
+ function getBrowserID(clientInfo) {
2222
+ return _async_to_generator(function() {
2223
+ return _ts_generator(this, function(_state) {
2224
+ switch(_state.label){
2225
+ case 0:
2226
+ if (cachedBrowserId) {
2227
+ return [
2228
+ 2,
2229
+ cachedBrowserId
2230
+ ];
2231
+ }
2232
+ return [
2233
+ 4,
2234
+ sha256Hex(resolvePlayerIdentitySeed(clientInfo))
2235
+ ];
2236
+ case 1:
2237
+ cachedBrowserId = _state.sent();
2238
+ return [
2239
+ 2,
2240
+ cachedBrowserId
2241
+ ];
2242
+ }
2243
+ });
2244
+ })();
2245
+ }
2246
+ function canPublish(licenseKey) {
2247
+ return Boolean(isMQTTEnabled() && licenseKey);
2248
+ }
2249
+ function buildPlayerMetricEvent() {
2250
+ return _async_to_generator(function() {
2251
+ var context, flags, _flags_captureAt, _flags_adLoaded, _flags_adDetect, clientInfo, playerId, captureAt;
2252
+ var _arguments = arguments;
2253
+ return _ts_generator(this, function(_state) {
2254
+ switch(_state.label){
2255
+ case 0:
2256
+ context = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {}, flags = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
2257
+ clientInfo = getClientInfo();
2258
+ return [
2259
+ 4,
2260
+ getBrowserID(clientInfo)
2261
+ ];
2262
+ case 1:
2263
+ playerId = _state.sent();
2264
+ captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
2265
+ return [
2266
+ 2,
2267
+ _object_spread({
2268
+ player_id: playerId,
2269
+ device_type: clientInfo.deviceType,
2270
+ os: clientInfo.os.toLowerCase(),
2271
+ ad_loaded: (_flags_adLoaded = flags.adLoaded) !== null && _flags_adLoaded !== void 0 ? _flags_adLoaded : false,
2272
+ ad_detect: (_flags_adDetect = flags.adDetect) !== null && _flags_adDetect !== void 0 ? _flags_adDetect : false,
2273
+ capture_at: captureAt
2274
+ }, context.inputStreamType ? {
2275
+ input_stream_type: context.inputStreamType
2276
+ } : {})
2277
+ ];
2278
+ }
2279
+ });
2280
+ }).apply(this, arguments);
2281
+ }
2282
+ function publishTracking(licenseKey, channel, body) {
2283
+ ensureMQTTClient();
2284
+ publishMQTT(buildPlayerTopic(licenseKey, channel), body);
2285
+ }
2286
+ function sendInitialTracking(_0) {
2287
+ return _async_to_generator(function(licenseKey) {
2288
+ var context, metricEvent, error;
2289
+ var _arguments = arguments;
2290
+ return _ts_generator(this, function(_state) {
2291
+ switch(_state.label){
2292
+ case 0:
2293
+ context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
2294
+ if (!canPublish(licenseKey)) return [
2295
+ 2
2296
+ ];
2297
+ _state.label = 1;
2298
+ case 1:
2299
+ _state.trys.push([
2300
+ 1,
2301
+ 3,
2302
+ ,
2303
+ 4
2304
+ ]);
2305
+ return [
2306
+ 4,
2307
+ buildPlayerMetricEvent(context, {
2308
+ adLoaded: false,
2309
+ adDetect: false
2310
+ })
1852
2311
  ];
1853
2312
  case 2:
1854
2313
  metricEvent = _state.sent();
@@ -2011,653 +2470,313 @@ function sendAdImpressionTracking(_0, _1) {
2011
2470
  console.error("[StormcloudVideoPlayer] Error sending ad impression tracking:", error);
2012
2471
  return [
2013
2472
  3,
2014
- 4
2015
- ];
2016
- case 4:
2017
- return [
2018
- 2
2019
- ];
2020
- }
2021
- });
2022
- }).apply(this, arguments);
2023
- }
2024
- function sendHeartbeat(_0) {
2025
- return _async_to_generator(function(licenseKey) {
2026
- var context, flags, heartbeatData, error;
2027
- var _arguments = arguments;
2028
- return _ts_generator(this, function(_state) {
2029
- switch(_state.label){
2030
- case 0:
2031
- context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {}, flags = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
2032
- if (!canPublish(licenseKey)) return [
2033
- 2
2034
- ];
2035
- _state.label = 1;
2036
- case 1:
2037
- _state.trys.push([
2038
- 1,
2039
- 3,
2040
- ,
2041
- 4
2042
- ]);
2043
- return [
2044
- 4,
2045
- buildPlayerMetricEvent(context, flags)
2046
- ];
2047
- case 2:
2048
- heartbeatData = _state.sent();
2049
- publishTracking(licenseKey, "heartbeat", heartbeatData);
2050
- return [
2051
- 3,
2052
- 4
2053
- ];
2054
- case 3:
2055
- error = _state.sent();
2056
- console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
2057
- return [
2058
- 3,
2059
- 4
2060
- ];
2061
- case 4:
2062
- return [
2063
- 2
2064
- ];
2065
- }
2066
- });
2067
- }).apply(this, arguments);
2068
- }
2069
- // src/utils/polyfills.ts
2070
- function polyfillURLSearchParams() {
2071
- if (typeof URLSearchParams !== "undefined") {
2072
- return;
2073
- }
2074
- var URLSearchParamsPolyfill = /*#__PURE__*/ function() {
2075
- "use strict";
2076
- function URLSearchParamsPolyfill(init) {
2077
- var _this = this;
2078
- _class_call_check(this, URLSearchParamsPolyfill);
2079
- this.params = /* @__PURE__ */ new Map();
2080
- if (typeof init === "string") {
2081
- this.parseQueryString(init);
2082
- } else if (_instanceof(init, URLSearchParamsPolyfill)) {
2083
- init.forEach(function(value, key) {
2084
- _this.append(key, value);
2085
- });
2086
- }
2087
- }
2088
- _create_class(URLSearchParamsPolyfill, [
2089
- {
2090
- key: "parseQueryString",
2091
- value: function parseQueryString(query) {
2092
- var _this = this;
2093
- var cleanQuery = query.startsWith("?") ? query.slice(1) : query;
2094
- if (!cleanQuery) return;
2095
- cleanQuery.split("&").forEach(function(param) {
2096
- var _param_split = _sliced_to_array(param.split("="), 2), key = _param_split[0], value = _param_split[1];
2097
- if (key) {
2098
- var decodedKey = _this.safeDecodeURIComponent(key);
2099
- var decodedValue = value ? _this.safeDecodeURIComponent(value) : "";
2100
- _this.append(decodedKey, decodedValue);
2101
- }
2102
- });
2103
- }
2104
- },
2105
- {
2106
- key: "safeDecodeURIComponent",
2107
- value: function safeDecodeURIComponent(str) {
2108
- try {
2109
- return decodeURIComponent(str.replace(/\+/g, " "));
2110
- } catch (e) {
2111
- return str;
2112
- }
2113
- }
2114
- },
2115
- {
2116
- key: "append",
2117
- value: function append(name, value) {
2118
- var values = this.params.get(name) || [];
2119
- values.push(String(value));
2120
- this.params.set(name, values);
2121
- }
2122
- },
2123
- {
2124
- key: "delete",
2125
- value: function _delete(name) {
2126
- this.params.delete(name);
2127
- }
2128
- },
2129
- {
2130
- key: "get",
2131
- value: function get(name) {
2132
- var values = this.params.get(name);
2133
- return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;
2134
- }
2135
- },
2136
- {
2137
- key: "getAll",
2138
- value: function getAll(name) {
2139
- return this.params.get(name) || [];
2140
- }
2141
- },
2142
- {
2143
- key: "has",
2144
- value: function has(name) {
2145
- return this.params.has(name);
2146
- }
2147
- },
2148
- {
2149
- key: "set",
2150
- value: function set(name, value) {
2151
- this.params.set(name, [
2152
- String(value)
2153
- ]);
2154
- }
2155
- },
2156
- {
2157
- key: "forEach",
2158
- value: function forEach(callback) {
2159
- var _this = this;
2160
- this.params.forEach(function(values, key) {
2161
- values.forEach(function(value) {
2162
- callback(value, key, _this);
2163
- });
2164
- });
2165
- }
2166
- },
2167
- {
2168
- key: "toString",
2169
- value: function toString() {
2170
- var parts = [];
2171
- this.params.forEach(function(values, key) {
2172
- values.forEach(function(value) {
2173
- parts.push("".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(value)));
2174
- });
2175
- });
2176
- return parts.join("&");
2177
- }
2178
- }
2179
- ]);
2180
- return URLSearchParamsPolyfill;
2181
- }();
2182
- window.URLSearchParams = URLSearchParamsPolyfill;
2183
- }
2184
- function polyfillTextEncoder() {
2185
- if (typeof TextEncoder !== "undefined") {
2186
- return;
2187
- }
2188
- var TextEncoderPolyfill = /*#__PURE__*/ function() {
2189
- "use strict";
2190
- function TextEncoderPolyfill() {
2191
- _class_call_check(this, TextEncoderPolyfill);
2192
- this.encoding = "utf-8";
2193
- }
2194
- _create_class(TextEncoderPolyfill, [
2195
- {
2196
- key: "encode",
2197
- value: function encode(str) {
2198
- var utf8 = [];
2199
- for(var i = 0; i < str.length; i++){
2200
- var charcode = str.charCodeAt(i);
2201
- if (charcode < 128) {
2202
- utf8.push(charcode);
2203
- } else if (charcode < 2048) {
2204
- utf8.push(192 | charcode >> 6, 128 | charcode & 63);
2205
- } else if (charcode < 55296 || charcode >= 57344) {
2206
- utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2207
- } else {
2208
- i++;
2209
- charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);
2210
- utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2211
- }
2212
- }
2213
- return new Uint8Array(utf8);
2214
- }
2215
- }
2216
- ]);
2217
- return TextEncoderPolyfill;
2218
- }();
2219
- window.TextEncoder = TextEncoderPolyfill;
2220
- }
2221
- function polyfillPromiseFinally() {
2222
- if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
2223
- Promise.prototype.finally = function(callback) {
2224
- var constructor = this.constructor;
2225
- return this.then(function(value) {
2226
- return constructor.resolve(callback()).then(function() {
2227
- return value;
2228
- });
2229
- }, function(reason) {
2230
- return constructor.resolve(callback()).then(function() {
2231
- throw reason;
2232
- });
2233
- });
2234
- };
2235
- }
2236
- }
2237
- function polyfillObjectAssign() {
2238
- if (typeof Object.assign !== "function") {
2239
- Object.assign = function(target) {
2240
- for(var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
2241
- sources[_key - 1] = arguments[_key];
2242
- }
2243
- if (target == null) {
2244
- throw new TypeError("Cannot convert undefined or null to object");
2245
- }
2246
- var to = Object(target);
2247
- for(var i = 0; i < sources.length; i++){
2248
- var nextSource = sources[i];
2249
- if (nextSource != null) {
2250
- for(var nextKey in nextSource){
2251
- if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
2252
- to[nextKey] = nextSource[nextKey];
2253
- }
2254
- }
2255
- }
2256
- }
2257
- return to;
2258
- };
2259
- }
2260
- }
2261
- function polyfillArrayFrom() {
2262
- if (!Array.from) {
2263
- Array.from = function(arrayLike, mapFn, thisArg) {
2264
- var items = Object(arrayLike);
2265
- if (arrayLike == null) {
2266
- throw new TypeError("Array.from requires an array-like object");
2267
- }
2268
- var len = items.length >>> 0;
2269
- var result = new Array(len);
2270
- for(var i = 0; i < len; i++){
2271
- if (mapFn) {
2272
- result[i] = mapFn.call(thisArg, items[i], i);
2273
- } else {
2274
- result[i] = items[i];
2275
- }
2276
- }
2277
- return result;
2278
- };
2279
- }
2280
- }
2281
- function polyfillStringStartsWith() {
2282
- if (!String.prototype.startsWith) {
2283
- String.prototype.startsWith = function(search, pos) {
2284
- pos = !pos || pos < 0 ? 0 : +pos;
2285
- return this.substring(pos, pos + search.length) === search;
2286
- };
2287
- }
2288
- }
2289
- function polyfillStringEndsWith() {
2290
- if (!String.prototype.endsWith) {
2291
- String.prototype.endsWith = function(search, length) {
2292
- if (length === void 0 || length > this.length) {
2293
- length = this.length;
2294
- }
2295
- return this.substring(length - search.length, length) === search;
2296
- };
2297
- }
2298
- }
2299
- function polyfillStringIncludes() {
2300
- if (!String.prototype.includes) {
2301
- String.prototype.includes = function(search, start) {
2302
- if (typeof start !== "number") {
2303
- start = 0;
2304
- }
2305
- if (start + search.length > this.length) {
2306
- return false;
2307
- }
2308
- return this.indexOf(search, start) !== -1;
2309
- };
2310
- }
2311
- }
2312
- function initializePolyfills() {
2313
- polyfillObjectAssign();
2314
- polyfillArrayFrom();
2315
- polyfillStringStartsWith();
2316
- polyfillStringEndsWith();
2317
- polyfillStringIncludes();
2318
- polyfillURLSearchParams();
2319
- polyfillTextEncoder();
2320
- polyfillPromiseFinally();
2321
- }
2322
- // src/utils/vastEnvironmentSignals.ts
2323
- var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
2324
- var AIRY_WEBOS_APP_ID = "com.freeairytv.webos";
2325
- var AIRY_TIZEN_APP_ID = "com.freeairytv.samsung";
2326
- var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
2327
- var AIRY_APP_NAME = "AiryTV Movies & TV";
2328
- var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
2329
- var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
2330
- var LG_TEST_APP_ID = "com.hulu.plus";
2331
- var LG_TEST_APP_NAME = "Hulu";
2332
- var LG_TEST_CONTENT_URL = "https://www.hulu.com/live-tv";
2333
- var _lgTestDeviceId;
2334
- function getLgTestDeviceId() {
2335
- if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();
2336
- return _lgTestDeviceId;
2337
- }
2338
- function isLgWebOS() {
2339
- if (typeof navigator === "undefined") return false;
2340
- return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);
2341
- }
2342
- function getDefaultAppId() {
2343
- if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
2344
- var ua = navigator.userAgent;
2345
- if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;
2346
- if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;
2347
- if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;
2348
- return AIRY_ANDROID_APP_ID;
2349
- }
2350
- var DEVICE_ID_STORAGE_KEYS = [
2351
- "rdid",
2352
- "ifa",
2353
- "advertisingId",
2354
- "advertising_id",
2355
- "deviceAdvertisingId",
2356
- "aaid",
2357
- "adid",
2358
- "rida",
2359
- "tifa",
2360
- "lgudid"
2361
- ];
2362
- var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
2363
- "aaid",
2364
- "adid"
2365
- ]);
2366
- function resolveVastEnvironmentSignals(isCtv) {
2367
- var _ref, _bridgeSignals_limitAdTracking;
2368
- var bridgeSignals = readNativeBridgeSignals();
2369
- var lg = isCtv && isLgWebOS();
2370
- var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || (lg ? getLgTestDeviceId() : void 0);
2371
- var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || inferDeviceIdType() || (lg ? "lgudid" : void 0);
2372
- var limitAdTracking = deviceId != null ? (_ref = (_bridgeSignals_limitAdTracking = bridgeSignals.limitAdTracking) !== null && _bridgeSignals_limitAdTracking !== void 0 ? _bridgeSignals_limitAdTracking : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false : void 0;
2373
- if (isCtv) {
2374
- return _object_spread_props(_object_spread({
2375
- isCtv: true,
2376
- contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),
2377
- appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || (lg ? LG_TEST_APP_ID : getDefaultAppId()),
2378
- appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),
2379
- sessionId: getOrCreateCtvSessionId()
2380
- }, deviceId ? {
2381
- deviceId: deviceId
2382
- } : {}, deviceIdType ? {
2383
- deviceIdType: deviceIdType
2384
- } : {}, limitAdTracking != null ? {
2385
- limitAdTracking: limitAdTracking
2386
- } : {}), {
2387
- deviceTypeHint: 5
2388
- });
2389
- }
2390
- return _object_spread({
2391
- isCtv: false
2392
- }, deviceId ? {
2393
- deviceId: deviceId
2394
- } : {}, deviceIdType ? {
2395
- deviceIdType: deviceIdType
2396
- } : {}, limitAdTracking != null ? {
2397
- limitAdTracking: limitAdTracking
2398
- } : {});
2399
- }
2400
- function inferDeviceIdType() {
2401
- if (typeof navigator === "undefined") {
2402
- return void 0;
2403
- }
2404
- var ua = navigator.userAgent;
2405
- if (/Roku/i.test(ua)) return "rida";
2406
- if (/Tizen|Samsung/i.test(ua)) return "tifa";
2407
- if (/AppleTV|Apple TV/i.test(ua)) return "tvOS";
2408
- if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
2409
- if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return "lgudid";
2410
- if (/Android|Google TV/i.test(ua)) return "aaid";
2411
- if (/iPhone|iPad|iPod/i.test(ua)) return "idfa";
2412
- return void 0;
2413
- }
2414
- function isEquivalentDeviceIdType(tagType, runtimeType) {
2415
- if (!tagType || !runtimeType) return false;
2416
- var tag = tagType.toLowerCase();
2417
- var runtime = runtimeType.toLowerCase();
2418
- if (tag === runtime) return true;
2419
- return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
2420
- }
2421
- function getOrCreateCtvSessionId() {
2422
- var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
2423
- if (existing) {
2424
- return existing;
2425
- }
2426
- var sessionId = createUuid();
2427
- try {
2428
- var _window_localStorage;
2429
- (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
2430
- } catch (unused) {}
2431
- return sessionId;
2473
+ 4
2474
+ ];
2475
+ case 4:
2476
+ return [
2477
+ 2
2478
+ ];
2479
+ }
2480
+ });
2481
+ }).apply(this, arguments);
2432
2482
  }
2433
- function createUuid() {
2434
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2435
- return crypto.randomUUID();
2436
- }
2437
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
2438
- var value = Math.floor(Math.random() * 16);
2439
- var nibble = char === "x" ? value : value & 3 | 8;
2440
- return nibble.toString(16);
2441
- });
2483
+ function sendHeartbeat(_0) {
2484
+ return _async_to_generator(function(licenseKey) {
2485
+ var context, flags, heartbeatData, error;
2486
+ var _arguments = arguments;
2487
+ return _ts_generator(this, function(_state) {
2488
+ switch(_state.label){
2489
+ case 0:
2490
+ context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {}, flags = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
2491
+ if (!canPublish(licenseKey)) return [
2492
+ 2
2493
+ ];
2494
+ _state.label = 1;
2495
+ case 1:
2496
+ _state.trys.push([
2497
+ 1,
2498
+ 3,
2499
+ ,
2500
+ 4
2501
+ ]);
2502
+ return [
2503
+ 4,
2504
+ buildPlayerMetricEvent(context, flags)
2505
+ ];
2506
+ case 2:
2507
+ heartbeatData = _state.sent();
2508
+ publishTracking(licenseKey, "heartbeat", heartbeatData);
2509
+ return [
2510
+ 3,
2511
+ 4
2512
+ ];
2513
+ case 3:
2514
+ error = _state.sent();
2515
+ console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
2516
+ return [
2517
+ 3,
2518
+ 4
2519
+ ];
2520
+ case 4:
2521
+ return [
2522
+ 2
2523
+ ];
2524
+ }
2525
+ });
2526
+ }).apply(this, arguments);
2442
2527
  }
2443
- function readNativeBridgeSignals() {
2444
- if (typeof window === "undefined") {
2445
- return {};
2528
+ // src/utils/polyfills.ts
2529
+ function polyfillURLSearchParams() {
2530
+ if (typeof URLSearchParams !== "undefined") {
2531
+ return;
2446
2532
  }
2447
- var candidates = [
2448
- window.__STORMCLOUD_CTV_AD_INFO__,
2449
- window.__STORMCLOUD_CTV__,
2450
- window.stormcloudCtv,
2451
- window.AiryTV,
2452
- window.Android,
2453
- window.webOS,
2454
- window.tizen,
2455
- window.amazon
2456
- ].filter(Boolean);
2457
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2458
- try {
2459
- for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2460
- var source = _step.value;
2461
- var contentUrl = readBridgeValue(source, [
2462
- "contentUrl",
2463
- "url",
2464
- "videoUrl",
2465
- "canonicalUrl"
2466
- ]) || void 0;
2467
- var appId = readBridgeValue(source, [
2468
- "appId",
2469
- "msid",
2470
- "applicationId",
2471
- "packageName"
2472
- ]) || void 0;
2473
- var appName = readBridgeValue(source, [
2474
- "appName",
2475
- "an",
2476
- "applicationName"
2477
- ]) || void 0;
2478
- var deviceId = readBridgeValue(source, [
2479
- "rdid",
2480
- "ifa",
2481
- "advertisingId",
2482
- "adId",
2483
- "deviceId",
2484
- "lgudid",
2485
- "LGUDID",
2486
- "tifa",
2487
- "rida",
2488
- "afai",
2489
- "aaid"
2490
- ]) || void 0;
2491
- if (!contentUrl && !deviceId && !appId && !appName) continue;
2492
- var deviceIdType = readBridgeValue(source, [
2493
- "idtype",
2494
- "deviceIdType",
2495
- "advertisingIdType",
2496
- "idType"
2497
- ]) || inferDeviceIdType();
2498
- var limitAdTracking = readBridgeBoolean(source, [
2499
- "is_lat",
2500
- "limitAdTracking",
2501
- "limitedAdTracking",
2502
- "lat"
2503
- ]);
2504
- return _object_spread({}, contentUrl ? {
2505
- contentUrl: contentUrl
2506
- } : {}, appId ? {
2507
- appId: appId
2508
- } : {}, appName ? {
2509
- appName: appName
2510
- } : {}, deviceId ? {
2511
- deviceId: deviceId
2512
- } : {}, deviceId && deviceIdType ? {
2513
- deviceIdType: deviceIdType
2514
- } : {}, deviceId && limitAdTracking != null ? {
2515
- limitAdTracking: limitAdTracking
2516
- } : {});
2517
- }
2518
- } catch (err) {
2519
- _didIteratorError = true;
2520
- _iteratorError = err;
2521
- } finally{
2522
- try {
2523
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2524
- _iterator.return();
2525
- }
2526
- } finally{
2527
- if (_didIteratorError) {
2528
- throw _iteratorError;
2533
+ var URLSearchParamsPolyfill = /*#__PURE__*/ function() {
2534
+ "use strict";
2535
+ function URLSearchParamsPolyfill(init) {
2536
+ var _this = this;
2537
+ _class_call_check(this, URLSearchParamsPolyfill);
2538
+ this.params = /* @__PURE__ */ new Map();
2539
+ if (typeof init === "string") {
2540
+ this.parseQueryString(init);
2541
+ } else if (_instanceof(init, URLSearchParamsPolyfill)) {
2542
+ init.forEach(function(value, key) {
2543
+ _this.append(key, value);
2544
+ });
2529
2545
  }
2530
2546
  }
2531
- }
2532
- return {};
2533
- }
2534
- function readBridgeValue(source, keys) {
2535
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2536
- try {
2537
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2538
- var key = _step.value;
2539
- var value = source === null || source === void 0 ? void 0 : source[key];
2540
- if (typeof value === "string" && value) {
2541
- return value;
2542
- }
2543
- if (typeof value === "function") {
2544
- try {
2545
- var result = value.call(source);
2546
- if (typeof result === "string" && result) {
2547
- return result;
2547
+ _create_class(URLSearchParamsPolyfill, [
2548
+ {
2549
+ key: "parseQueryString",
2550
+ value: function parseQueryString(query) {
2551
+ var _this = this;
2552
+ var cleanQuery = query.startsWith("?") ? query.slice(1) : query;
2553
+ if (!cleanQuery) return;
2554
+ cleanQuery.split("&").forEach(function(param) {
2555
+ var _param_split = _sliced_to_array(param.split("="), 2), key = _param_split[0], value = _param_split[1];
2556
+ if (key) {
2557
+ var decodedKey = _this.safeDecodeURIComponent(key);
2558
+ var decodedValue = value ? _this.safeDecodeURIComponent(value) : "";
2559
+ _this.append(decodedKey, decodedValue);
2560
+ }
2561
+ });
2562
+ }
2563
+ },
2564
+ {
2565
+ key: "safeDecodeURIComponent",
2566
+ value: function safeDecodeURIComponent(str) {
2567
+ try {
2568
+ return decodeURIComponent(str.replace(/\+/g, " "));
2569
+ } catch (e) {
2570
+ return str;
2548
2571
  }
2549
- } catch (unused) {}
2572
+ }
2573
+ },
2574
+ {
2575
+ key: "append",
2576
+ value: function append(name, value) {
2577
+ var values = this.params.get(name) || [];
2578
+ values.push(String(value));
2579
+ this.params.set(name, values);
2580
+ }
2581
+ },
2582
+ {
2583
+ key: "delete",
2584
+ value: function _delete(name) {
2585
+ this.params.delete(name);
2586
+ }
2587
+ },
2588
+ {
2589
+ key: "get",
2590
+ value: function get(name) {
2591
+ var values = this.params.get(name);
2592
+ return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;
2593
+ }
2594
+ },
2595
+ {
2596
+ key: "getAll",
2597
+ value: function getAll(name) {
2598
+ return this.params.get(name) || [];
2599
+ }
2600
+ },
2601
+ {
2602
+ key: "has",
2603
+ value: function has(name) {
2604
+ return this.params.has(name);
2605
+ }
2606
+ },
2607
+ {
2608
+ key: "set",
2609
+ value: function set(name, value) {
2610
+ this.params.set(name, [
2611
+ String(value)
2612
+ ]);
2613
+ }
2614
+ },
2615
+ {
2616
+ key: "forEach",
2617
+ value: function forEach(callback) {
2618
+ var _this = this;
2619
+ this.params.forEach(function(values, key) {
2620
+ values.forEach(function(value) {
2621
+ callback(value, key, _this);
2622
+ });
2623
+ });
2624
+ }
2625
+ },
2626
+ {
2627
+ key: "toString",
2628
+ value: function toString() {
2629
+ var parts = [];
2630
+ this.params.forEach(function(values, key) {
2631
+ values.forEach(function(value) {
2632
+ parts.push("".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(value)));
2633
+ });
2634
+ });
2635
+ return parts.join("&");
2636
+ }
2550
2637
  }
2638
+ ]);
2639
+ return URLSearchParamsPolyfill;
2640
+ }();
2641
+ window.URLSearchParams = URLSearchParamsPolyfill;
2642
+ }
2643
+ function polyfillTextEncoder() {
2644
+ if (typeof TextEncoder !== "undefined") {
2645
+ return;
2646
+ }
2647
+ var TextEncoderPolyfill = /*#__PURE__*/ function() {
2648
+ "use strict";
2649
+ function TextEncoderPolyfill() {
2650
+ _class_call_check(this, TextEncoderPolyfill);
2651
+ this.encoding = "utf-8";
2551
2652
  }
2552
- } catch (err) {
2553
- _didIteratorError = true;
2554
- _iteratorError = err;
2555
- } finally{
2556
- try {
2557
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2558
- _iterator.return();
2559
- }
2560
- } finally{
2561
- if (_didIteratorError) {
2562
- throw _iteratorError;
2653
+ _create_class(TextEncoderPolyfill, [
2654
+ {
2655
+ key: "encode",
2656
+ value: function encode(str) {
2657
+ var utf8 = [];
2658
+ for(var i = 0; i < str.length; i++){
2659
+ var charcode = str.charCodeAt(i);
2660
+ if (charcode < 128) {
2661
+ utf8.push(charcode);
2662
+ } else if (charcode < 2048) {
2663
+ utf8.push(192 | charcode >> 6, 128 | charcode & 63);
2664
+ } else if (charcode < 55296 || charcode >= 57344) {
2665
+ utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2666
+ } else {
2667
+ i++;
2668
+ charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);
2669
+ utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2670
+ }
2671
+ }
2672
+ return new Uint8Array(utf8);
2673
+ }
2563
2674
  }
2564
- }
2675
+ ]);
2676
+ return TextEncoderPolyfill;
2677
+ }();
2678
+ window.TextEncoder = TextEncoderPolyfill;
2679
+ }
2680
+ function polyfillPromiseFinally() {
2681
+ if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
2682
+ Promise.prototype.finally = function(callback) {
2683
+ var constructor = this.constructor;
2684
+ return this.then(function(value) {
2685
+ return constructor.resolve(callback()).then(function() {
2686
+ return value;
2687
+ });
2688
+ }, function(reason) {
2689
+ return constructor.resolve(callback()).then(function() {
2690
+ throw reason;
2691
+ });
2692
+ });
2693
+ };
2565
2694
  }
2566
- return void 0;
2567
2695
  }
2568
- function readBridgeBoolean(source, keys) {
2569
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2570
- try {
2571
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2572
- var key = _step.value;
2573
- var value = source === null || source === void 0 ? void 0 : source[key];
2574
- var normalized = normalizeBoolean(value);
2575
- if (normalized != null) {
2576
- return normalized;
2577
- }
2578
- if (typeof value === "function") {
2579
- try {
2580
- var result = normalizeBoolean(value.call(source));
2581
- if (result != null) {
2582
- return result;
2583
- }
2584
- } catch (unused) {}
2696
+ function polyfillObjectAssign() {
2697
+ if (typeof Object.assign !== "function") {
2698
+ Object.assign = function(target) {
2699
+ for(var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
2700
+ sources[_key - 1] = arguments[_key];
2585
2701
  }
2586
- }
2587
- } catch (err) {
2588
- _didIteratorError = true;
2589
- _iteratorError = err;
2590
- } finally{
2591
- try {
2592
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2593
- _iterator.return();
2702
+ if (target == null) {
2703
+ throw new TypeError("Cannot convert undefined or null to object");
2594
2704
  }
2595
- } finally{
2596
- if (_didIteratorError) {
2597
- throw _iteratorError;
2705
+ var to = Object(target);
2706
+ for(var i = 0; i < sources.length; i++){
2707
+ var nextSource = sources[i];
2708
+ if (nextSource != null) {
2709
+ for(var nextKey in nextSource){
2710
+ if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
2711
+ to[nextKey] = nextSource[nextKey];
2712
+ }
2713
+ }
2714
+ }
2598
2715
  }
2599
- }
2716
+ return to;
2717
+ };
2600
2718
  }
2601
- return void 0;
2602
2719
  }
2603
- function readStoredDeviceId() {
2604
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2605
- try {
2606
- for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2607
- var key = _step.value;
2608
- var value = readStoredString(key);
2609
- if (value) {
2610
- return value;
2611
- }
2612
- }
2613
- } catch (err) {
2614
- _didIteratorError = true;
2615
- _iteratorError = err;
2616
- } finally{
2617
- try {
2618
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2619
- _iterator.return();
2720
+ function polyfillArrayFrom() {
2721
+ if (!Array.from) {
2722
+ Array.from = function(arrayLike, mapFn, thisArg) {
2723
+ var items = Object(arrayLike);
2724
+ if (arrayLike == null) {
2725
+ throw new TypeError("Array.from requires an array-like object");
2620
2726
  }
2621
- } finally{
2622
- if (_didIteratorError) {
2623
- throw _iteratorError;
2727
+ var len = items.length >>> 0;
2728
+ var result = new Array(len);
2729
+ for(var i = 0; i < len; i++){
2730
+ if (mapFn) {
2731
+ result[i] = mapFn.call(thisArg, items[i], i);
2732
+ } else {
2733
+ result[i] = items[i];
2734
+ }
2624
2735
  }
2625
- }
2736
+ return result;
2737
+ };
2626
2738
  }
2627
- return void 0;
2628
2739
  }
2629
- function readStoredString(key) {
2630
- if (typeof window === "undefined") {
2631
- return void 0;
2632
- }
2633
- try {
2634
- var _window_localStorage;
2635
- var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
2636
- return value || void 0;
2637
- } catch (unused) {
2638
- return void 0;
2740
+ function polyfillStringStartsWith() {
2741
+ if (!String.prototype.startsWith) {
2742
+ String.prototype.startsWith = function(search, pos) {
2743
+ pos = !pos || pos < 0 ? 0 : +pos;
2744
+ return this.substring(pos, pos + search.length) === search;
2745
+ };
2639
2746
  }
2640
2747
  }
2641
- function readStoredLimitAdTracking() {
2642
- return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
2643
- }
2644
- function normalizeBoolean(value) {
2645
- if (typeof value === "boolean") {
2646
- return value;
2647
- }
2648
- if (typeof value === "number") {
2649
- return value === 1;
2748
+ function polyfillStringEndsWith() {
2749
+ if (!String.prototype.endsWith) {
2750
+ String.prototype.endsWith = function(search, length) {
2751
+ if (length === void 0 || length > this.length) {
2752
+ length = this.length;
2753
+ }
2754
+ return this.substring(length - search.length, length) === search;
2755
+ };
2650
2756
  }
2651
- if (typeof value === "string") {
2652
- var normalized = value.toLowerCase();
2653
- if (normalized === "1" || normalized === "true" || normalized === "yes") {
2654
- return true;
2655
- }
2656
- if (normalized === "0" || normalized === "false" || normalized === "no") {
2657
- return false;
2658
- }
2757
+ }
2758
+ function polyfillStringIncludes() {
2759
+ if (!String.prototype.includes) {
2760
+ String.prototype.includes = function(search, start) {
2761
+ if (typeof start !== "number") {
2762
+ start = 0;
2763
+ }
2764
+ if (start + search.length > this.length) {
2765
+ return false;
2766
+ }
2767
+ return this.indexOf(search, start) !== -1;
2768
+ };
2659
2769
  }
2660
- return void 0;
2770
+ }
2771
+ function initializePolyfills() {
2772
+ polyfillObjectAssign();
2773
+ polyfillArrayFrom();
2774
+ polyfillStringStartsWith();
2775
+ polyfillStringEndsWith();
2776
+ polyfillStringIncludes();
2777
+ polyfillURLSearchParams();
2778
+ polyfillTextEncoder();
2779
+ polyfillPromiseFinally();
2661
2780
  }
2662
2781
  // src/utils/vastMacros.ts
2663
2782
  var UNEXPANDED_MACRO_PATTERN = /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/;
@@ -2780,7 +2899,7 @@ var INLINE_DEVICE_MACRO_REPLACEMENTS = [
2780
2899
  }
2781
2900
  }
2782
2901
  ];
2783
- function isMacroPlaceholder(value) {
2902
+ function isMacroPlaceholder2(value) {
2784
2903
  if (value == null) return true;
2785
2904
  var trimmed = value.trim();
2786
2905
  if (!trimmed) return true;
@@ -2839,11 +2958,11 @@ function applyDeviceIdentityParams(params, ctx) {
2839
2958
  if (runtimeId) {
2840
2959
  params.set("rdid", runtimeId);
2841
2960
  params.set("idtype", runtimeType || tagType || "aaid");
2842
- params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder(tagLat) ? "0" : tagLat);
2961
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder2(tagLat) ? "0" : tagLat);
2843
2962
  return;
2844
2963
  }
2845
- var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));
2846
- var tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));
2964
+ var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder2(tagRdid));
2965
+ var tagTypeValid = Boolean(tagType && !isMacroPlaceholder2(tagType));
2847
2966
  if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
2848
2967
  params.delete("rdid");
2849
2968
  params.delete("idtype");
@@ -2851,10 +2970,10 @@ function applyDeviceIdentityParams(params, ctx) {
2851
2970
  return;
2852
2971
  }
2853
2972
  if (tagRdidValid) {
2854
- if (isMacroPlaceholder(tagType) && runtimeType) {
2973
+ if (isMacroPlaceholder2(tagType) && runtimeType) {
2855
2974
  params.set("idtype", runtimeType);
2856
2975
  }
2857
- if (isMacroPlaceholder(tagLat)) {
2976
+ if (isMacroPlaceholder2(tagLat)) {
2858
2977
  params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : "0");
2859
2978
  }
2860
2979
  return;
@@ -3040,7 +3159,7 @@ function applyVastMacros(baseUrl, ctx) {
3040
3159
  }
3041
3160
  var staleKeys = [];
3042
3161
  params.forEach(function(value, key) {
3043
- if (isMacroPlaceholder(value)) {
3162
+ if (isMacroPlaceholder2(value)) {
3044
3163
  staleKeys.push(key);
3045
3164
  }
3046
3165
  });
@@ -6019,7 +6138,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6019
6138
  key: "setupNativeHls",
6020
6139
  value: function setupNativeHls() {
6021
6140
  return _async_to_generator(function() {
6022
- var _this_config_isLiveStream, _this_config_lowLatencyMode, _this_video_play;
6141
+ var _this_config_isLiveStream, _this_config_lowLatencyMode, adBehavior, _this_video_play;
6023
6142
  return _ts_generator(this, function(_state) {
6024
6143
  switch(_state.label){
6025
6144
  case 0:
@@ -6028,10 +6147,11 @@ var HlsEngine = /*#__PURE__*/ function() {
6028
6147
  this.video.src = this.config.src;
6029
6148
  this.isLiveStream = (_this_config_isLiveStream = this.config.isLiveStream) !== null && _this_config_isLiveStream !== void 0 ? _this_config_isLiveStream : (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false;
6030
6149
  if (this.debug) {
6031
- console.log("[StormcloudVideoPlayer] Using native HLS playback - VOD mode:", {
6150
+ adBehavior = this.isLiveStream ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
6151
+ console.log("[StormcloudVideoPlayer] Using native HLS playback:", {
6032
6152
  isLive: this.isLiveStream,
6033
6153
  allowNativeHls: this.config.allowNativeHls,
6034
- adBehavior: "vod (main video pauses during ads)"
6154
+ adBehavior: adBehavior
6035
6155
  });
6036
6156
  }
6037
6157
  if (!this.config.autoplay) return [
@@ -6440,6 +6560,14 @@ var HlsEngine = /*#__PURE__*/ function() {
6440
6560
  });
6441
6561
  }
6442
6562
  },
6563
+ {
6564
+ key: "getLiveSyncPosition",
6565
+ value: function getLiveSyncPosition() {
6566
+ var _this_hls;
6567
+ var pos = (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.liveSyncPosition;
6568
+ return typeof pos === "number" && Number.isFinite(pos) ? pos : void 0;
6569
+ }
6570
+ },
6443
6571
  {
6444
6572
  key: "destroy",
6445
6573
  value: function destroy() {
@@ -8015,6 +8143,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8015
8143
  this.host.video.volume = restoredVolume;
8016
8144
  }
8017
8145
  if (this.host.shouldContinueLiveStreamDuringAds()) {
8146
+ var liveSyncPos = this.host.getLiveSyncPosition();
8147
+ if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
8148
+ if (this.debug) {
8149
+ console.log("[StormcloudVideoPlayer] Live break end — snapping to live edge: ".concat(this.host.video.currentTime.toFixed(2), "s → ").concat(liveSyncPos.toFixed(2), "s"));
8150
+ }
8151
+ this.host.video.currentTime = liveSyncPos;
8152
+ }
8018
8153
  if (this.host.video.paused) {
8019
8154
  var _this_host_video_play;
8020
8155
  if (this.debug) console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
@@ -8158,6 +8293,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8158
8293
  shouldContinueLiveStreamDuringAds: function shouldContinueLiveStreamDuringAds() {
8159
8294
  return _this.shouldContinueLiveStreamDuringAds();
8160
8295
  },
8296
+ getLiveSyncPosition: function getLiveSyncPosition() {
8297
+ return _this.hlsEngine.getLiveSyncPosition();
8298
+ },
8161
8299
  generateVastUrls: function generateVastUrls(base, count) {
8162
8300
  return _this.generateVastUrls(base, count);
8163
8301
  }
@@ -8199,7 +8337,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8199
8337
  // ───────────────────────────────────────────────────────────────
8200
8338
  function load() {
8201
8339
  return _async_to_generator(function() {
8202
- var _this, _this_config_lowLatencyMode, error;
8340
+ var _this, _this_config_lowLatencyMode, error, continueLiveStreamDuringAds;
8203
8341
  return _ts_generator(this, function(_state) {
8204
8342
  switch(_state.label){
8205
8343
  case 0:
@@ -8253,15 +8391,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8253
8391
  3,
8254
8392
  6
8255
8393
  ];
8256
- this.adPlayer.destroy();
8257
- this.adPlayer = this.createAdPlayer(false);
8258
- this.adPlayer.initialize();
8259
8394
  return [
8260
8395
  4,
8261
8396
  this.hlsEngine.setupNativeHls()
8262
8397
  ];
8263
8398
  case 5:
8264
8399
  _state.sent();
8400
+ continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();
8401
+ if (this.debug) {
8402
+ console.log("[StormcloudVideoPlayer] Native HLS ad behavior:", {
8403
+ isLive: this.hlsEngine.isLiveStream,
8404
+ continueLiveStreamDuringAds: continueLiveStreamDuringAds
8405
+ });
8406
+ }
8407
+ this.adPlayer.destroy();
8408
+ this.adPlayer = this.createAdPlayer(continueLiveStreamDuringAds);
8409
+ this.adPlayer.initialize();
8265
8410
  return [
8266
8411
  2
8267
8412
  ];
@@ -8369,9 +8514,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8369
8514
  {
8370
8515
  key: "shouldContinueLiveStreamDuringAds",
8371
8516
  value: function shouldContinueLiveStreamDuringAds() {
8372
- if (this.config.allowNativeHls) return false;
8373
- if (!this.hlsEngine.isLiveStream) return false;
8374
- return true;
8517
+ if (this.hlsEngine.isLiveStream) {
8518
+ return true;
8519
+ }
8520
+ var duration = this.video.duration;
8521
+ if (!Number.isFinite(duration) || duration === Infinity) {
8522
+ return true;
8523
+ }
8524
+ return false;
8375
8525
  }
8376
8526
  },
8377
8527
  {
@@ -8669,9 +8819,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8669
8819
  this.adBreak.showAds = true;
8670
8820
  this.adBreak.inAdBreak = true;
8671
8821
  this.timing.currentAdBreakStartWallClockMs = Date.now();
8672
- if (!this.video.paused) {
8673
- this.video.pause();
8674
- }
8675
8822
  _state.label = 1;
8676
8823
  case 1:
8677
8824
  _state.trys.push([
@@ -9045,7 +9192,8 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
9045
9192
  setShowSpeedMenu(false);
9046
9193
  };
9047
9194
  var isHlsStream = (src === null || src === void 0 ? void 0 : src.toLowerCase().includes(".m3u8")) || (src === null || src === void 0 ? void 0 : src.toLowerCase().includes("/hls/"));
9048
- var shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls || isLiveStream === false : true);
9195
+ var isLiveUiMode = isLiveStream === true;
9196
+ var shouldShowEnhancedControls = showCustomControls && (isHlsStream ? !isLiveUiMode : true);
9049
9197
  var criticalPropsKey = useMemo(function() {
9050
9198
  return CRITICAL_PROPS.map(function(prop) {
9051
9199
  return "".concat(prop, ":").concat(props[prop]);
@@ -10426,6 +10574,7 @@ var HlsPlayer = /*#__PURE__*/ function(Component) {
10426
10574
  if (_this1.props.muted !== void 0) config.muted = _this1.props.muted;
10427
10575
  if (_this1.props.lowLatencyMode !== void 0) config.lowLatencyMode = _this1.props.lowLatencyMode;
10428
10576
  if (_this1.props.allowNativeHls !== void 0) config.allowNativeHls = _this1.props.allowNativeHls;
10577
+ if (_this1.props.isLiveStream !== void 0) config.isLiveStream = _this1.props.isLiveStream;
10429
10578
  if (_this1.props.driftToleranceMs !== void 0) config.driftToleranceMs = _this1.props.driftToleranceMs;
10430
10579
  if (_this1.props.immediateManifestAds !== void 0) config.immediateManifestAds = _this1.props.immediateManifestAds;
10431
10580
  if (_this1.props.debugAdTiming !== void 0) config.debugAdTiming = _this1.props.debugAdTiming;
@@ -11194,6 +11343,7 @@ var SUPPORTED_PROPS = [
11194
11343
  "wrapperStyle",
11195
11344
  "allowNativeHls",
11196
11345
  "lowLatencyMode",
11346
+ "isLiveStream",
11197
11347
  "driftToleranceMs",
11198
11348
  "immediateManifestAds",
11199
11349
  "debugAdTiming",