@hopeplayer/core 1.0.16 → 1.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +24 -14
  2. package/dist/HopePlayerElement.d.ts +3 -0
  3. package/dist/HopePlayerElement.d.ts.map +1 -1
  4. package/dist/chunks/{index-CWLyz1fp.js → adTriggers-DXmtF4t2.js} +113 -118
  5. package/dist/chunks/adTriggers-DXmtF4t2.js.map +1 -0
  6. package/dist/chunks/{index-DITXYcHx.js → ads-MCG5a6eK.js} +130 -125
  7. package/dist/chunks/ads-MCG5a6eK.js.map +1 -0
  8. package/dist/chunks/{index-BeJNpAyx.js → audio-LkYgd5Wq.js} +7 -7
  9. package/dist/chunks/audio-LkYgd5Wq.js.map +1 -0
  10. package/dist/chunks/{ScratchSound-0XKHUcJK.js → audioScratchSound-7XkwCCDm.js} +1 -1
  11. package/dist/chunks/audioScratchSound-7XkwCCDm.js.map +1 -0
  12. package/dist/chunks/{index-Miba3PD_.js → cast-bMrkGGuD.js} +70 -66
  13. package/dist/chunks/cast-bMrkGGuD.js.map +1 -0
  14. package/dist/chunks/{index-rENB3n9O.js → countdownScreen-CI-u6jjA.js} +1 -1
  15. package/dist/chunks/countdownScreen-CI-u6jjA.js.map +1 -0
  16. package/dist/chunks/{index-Q8FMOHj0.js → dai-B9Tth1Iv.js} +1 -1
  17. package/dist/chunks/dai-B9Tth1Iv.js.map +1 -0
  18. package/dist/chunks/{index-DCXX1ZJG.js → debugPanel-Bnc_7GOn.js} +1 -1
  19. package/dist/chunks/debugPanel-Bnc_7GOn.js.map +1 -0
  20. package/dist/chunks/{index-DXWK4EFa.js → dubbing-kNMPpyHl.js} +1 -1
  21. package/dist/chunks/dubbing-kNMPpyHl.js.map +1 -0
  22. package/dist/chunks/{index-BBmuCtKu.js → geoChecker-BRtvHwI-.js} +1 -1
  23. package/dist/chunks/geoChecker-BRtvHwI-.js.map +1 -0
  24. package/dist/chunks/{index-Ca8hocby.js → gesture-BzPCgi87.js} +1 -1
  25. package/dist/chunks/gesture-BzPCgi87.js.map +1 -0
  26. package/dist/chunks/{loadGpt-CmiAy366.js → gpt-CGXHTG_H.js} +1 -1
  27. package/dist/chunks/gpt-CGXHTG_H.js.map +1 -0
  28. package/dist/chunks/{index-3QALpwsf.js → inViewAutoplay-CRJe7GA4.js} +1 -1
  29. package/dist/chunks/inViewAutoplay-CRJe7GA4.js.map +1 -0
  30. package/dist/chunks/{index-7IBf8Y-R.js → liveWallClock-ChUTtzLD.js} +1 -1
  31. package/dist/chunks/liveWallClock-ChUTtzLD.js.map +1 -0
  32. package/dist/chunks/{index-f0vSgRIK.js → loopSection-CvF4l5uf.js} +1 -1
  33. package/dist/chunks/loopSection-CvF4l5uf.js.map +1 -0
  34. package/dist/chunks/{index-e00_M05B.js → markers-BhMJLPqj.js} +2 -2
  35. package/dist/chunks/markers-BhMJLPqj.js.map +1 -0
  36. package/dist/chunks/{index-CDPrkLq0.js → pauseAd-BQQe21X4.js} +2 -2
  37. package/dist/chunks/pauseAd-BQQe21X4.js.map +1 -0
  38. package/dist/chunks/{index-DEv3YqLg.js → player-DW5iWvPs.js} +939 -880
  39. package/dist/chunks/player-DW5iWvPs.js.map +1 -0
  40. package/dist/chunks/{index-D3Z7ZDLJ.js → playlist-DYGbJ5wz.js} +24 -24
  41. package/dist/chunks/playlist-DYGbJ5wz.js.map +1 -0
  42. package/dist/chunks/{VideoPrebid-CpckFzSq.js → prebid-CRY3i2OT.js} +1 -1
  43. package/dist/chunks/prebid-CRY3i2OT.js.map +1 -0
  44. package/dist/chunks/{index-DT8-oMPm.js → qrResume-DXwD3oSA.js} +29 -30
  45. package/dist/chunks/qrResume-DXwD3oSA.js.map +1 -0
  46. package/dist/chunks/redirectScreen-CSjrS8Kg.js +208 -0
  47. package/dist/chunks/redirectScreen-CSjrS8Kg.js.map +1 -0
  48. package/dist/chunks/{index-BbRYOSvk.js → rewardedUnlock-DZ_qPcDG.js} +22 -19
  49. package/dist/chunks/rewardedUnlock-DZ_qPcDG.js.map +1 -0
  50. package/dist/chunks/seekWhenReady-Clzne3-S.js +32 -0
  51. package/dist/chunks/seekWhenReady-Clzne3-S.js.map +1 -0
  52. package/dist/chunks/{index-CBX7bn-G.js → segments-LsZPlbYi.js} +2 -2
  53. package/dist/chunks/segments-LsZPlbYi.js.map +1 -0
  54. package/dist/chunks/{index-Ch3ep-eJ.js → sponsorship-BT21uwN5.js} +36 -41
  55. package/dist/chunks/sponsorship-BT21uwN5.js.map +1 -0
  56. package/dist/chunks/{index-BXSND_xN.js → spriteThumbnails-BQkEBRu-.js} +2 -2
  57. package/dist/chunks/spriteThumbnails-BQkEBRu-.js.map +1 -0
  58. package/dist/chunks/{index-DGtpFgHV.js → statsPanel-DSClIwA3.js} +1 -1
  59. package/dist/chunks/statsPanel-DSClIwA3.js.map +1 -0
  60. package/dist/chunks/{index-CDDke5rz.js → sticky-D_eLCNFk.js} +1 -1
  61. package/dist/chunks/sticky-D_eLCNFk.js.map +1 -0
  62. package/dist/chunks/{index-C3BQGcT3.js → story-H6f7gSoX.js} +27 -15
  63. package/dist/chunks/story-H6f7gSoX.js.map +1 -0
  64. package/dist/chunks/{index-C5oGMHF_.js → tapGestures-DrC42DiI.js} +1 -1
  65. package/dist/chunks/tapGestures-DrC42DiI.js.map +1 -0
  66. package/dist/chunks/trackingPixel-D2wxdCEz.js +20 -0
  67. package/dist/chunks/trackingPixel-D2wxdCEz.js.map +1 -0
  68. package/dist/controls/SeekBar.d.ts.map +1 -1
  69. package/dist/hls/SourceManager.d.ts.map +1 -1
  70. package/dist/hope-player.js +1 -1
  71. package/dist/i18n/locales/en.d.ts.map +1 -1
  72. package/dist/i18n/locales/tr.d.ts.map +1 -1
  73. package/dist/i18n/types.d.ts +3 -0
  74. package/dist/i18n/types.d.ts.map +1 -1
  75. package/dist/index.d.ts +1 -1
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/keyboard/KeyboardController.d.ts.map +1 -1
  78. package/dist/plugins/ad-triggers/AdTriggers.d.ts.map +1 -1
  79. package/dist/plugins/ads/AdsController.d.ts.map +1 -1
  80. package/dist/plugins/ads/generateVastUrl.d.ts +10 -0
  81. package/dist/plugins/ads/generateVastUrl.d.ts.map +1 -1
  82. package/dist/plugins/cast/CastController.d.ts.map +1 -1
  83. package/dist/plugins/playlist/PlaylistRunner.d.ts.map +1 -1
  84. package/dist/plugins/qr-resume/QrResume.d.ts.map +1 -1
  85. package/dist/plugins/redirect-screen/RedirectScreen.d.ts +26 -3
  86. package/dist/plugins/redirect-screen/RedirectScreen.d.ts.map +1 -1
  87. package/dist/plugins/rewarded/RewardedUnlock.d.ts +0 -5
  88. package/dist/plugins/rewarded/RewardedUnlock.d.ts.map +1 -1
  89. package/dist/plugins/shared/seekWhenReady.d.ts +22 -0
  90. package/dist/plugins/shared/seekWhenReady.d.ts.map +1 -0
  91. package/dist/plugins/shared/trackingPixel.d.ts +8 -0
  92. package/dist/plugins/shared/trackingPixel.d.ts.map +1 -0
  93. package/dist/plugins/sponsorship/SponsorshipLayer.d.ts.map +1 -1
  94. package/dist/plugins/story/HopeStory.d.ts +2 -0
  95. package/dist/plugins/story/HopeStory.d.ts.map +1 -1
  96. package/dist/screens/ErrorScreen.d.ts +7 -0
  97. package/dist/screens/ErrorScreen.d.ts.map +1 -1
  98. package/dist/types/index.d.ts +49 -1
  99. package/dist/types/index.d.ts.map +1 -1
  100. package/dist/utils/media-error.d.ts +10 -0
  101. package/dist/utils/media-error.d.ts.map +1 -0
  102. package/dist/utils/seek-by.d.ts +8 -0
  103. package/dist/utils/seek-by.d.ts.map +1 -1
  104. package/package.json +4 -1
  105. package/dist/chunks/ScratchSound-0XKHUcJK.js.map +0 -1
  106. package/dist/chunks/VideoPrebid-CpckFzSq.js.map +0 -1
  107. package/dist/chunks/index-3QALpwsf.js.map +0 -1
  108. package/dist/chunks/index-7IBf8Y-R.js.map +0 -1
  109. package/dist/chunks/index-BBmuCtKu.js.map +0 -1
  110. package/dist/chunks/index-BXSND_xN.js.map +0 -1
  111. package/dist/chunks/index-BbRYOSvk.js.map +0 -1
  112. package/dist/chunks/index-BeJNpAyx.js.map +0 -1
  113. package/dist/chunks/index-C3BQGcT3.js.map +0 -1
  114. package/dist/chunks/index-C5oGMHF_.js.map +0 -1
  115. package/dist/chunks/index-CBX7bn-G.js.map +0 -1
  116. package/dist/chunks/index-CDDke5rz.js.map +0 -1
  117. package/dist/chunks/index-CDPrkLq0.js.map +0 -1
  118. package/dist/chunks/index-CWLyz1fp.js.map +0 -1
  119. package/dist/chunks/index-Ca8hocby.js.map +0 -1
  120. package/dist/chunks/index-Ch3ep-eJ.js.map +0 -1
  121. package/dist/chunks/index-D3Z7ZDLJ.js.map +0 -1
  122. package/dist/chunks/index-D6r-BGAV.js +0 -77
  123. package/dist/chunks/index-D6r-BGAV.js.map +0 -1
  124. package/dist/chunks/index-DCXX1ZJG.js.map +0 -1
  125. package/dist/chunks/index-DEv3YqLg.js.map +0 -1
  126. package/dist/chunks/index-DGtpFgHV.js.map +0 -1
  127. package/dist/chunks/index-DITXYcHx.js.map +0 -1
  128. package/dist/chunks/index-DT8-oMPm.js.map +0 -1
  129. package/dist/chunks/index-DXWK4EFa.js.map +0 -1
  130. package/dist/chunks/index-Miba3PD_.js.map +0 -1
  131. package/dist/chunks/index-Q8FMOHj0.js.map +0 -1
  132. package/dist/chunks/index-e00_M05B.js.map +0 -1
  133. package/dist/chunks/index-f0vSgRIK.js.map +0 -1
  134. package/dist/chunks/index-rENB3n9O.js.map +0 -1
  135. package/dist/chunks/loadGpt-CmiAy366.js.map +0 -1
@@ -1,30 +1,31 @@
1
- var k = Object.defineProperty;
2
- var x = (l, t, e) => t in l ? k(l, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : l[t] = e;
1
+ var A = Object.defineProperty;
2
+ var x = (l, t, e) => t in l ? A(l, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : l[t] = e;
3
3
  var r = (l, t, e) => x(l, typeof t != "symbol" ? t + "" : t, e);
4
- import { s as E } from "./index-DEv3YqLg.js";
5
- const T = "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1", C = 1e4;
4
+ import { s as E } from "./player-DW5iWvPs.js";
5
+ import { s as T } from "./seekWhenReady-Clzne3-S.js";
6
+ const C = "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1", w = 1e4;
6
7
  let g = null;
7
8
  function b() {
8
9
  var t, e;
9
10
  const l = window;
10
11
  return (t = l.cast) != null && t.framework && ((e = l.chrome) != null && e.cast) ? { framework: l.cast.framework, chrome: l.chrome.cast } : null;
11
12
  }
12
- function w() {
13
+ function I() {
13
14
  if (g) return g;
14
15
  const l = window;
15
16
  return b() ? g = Promise.resolve(b()) : !l.chrome || !window.isSecureContext ? g = Promise.resolve(null) : (g = new Promise((t) => {
16
- const e = l.__onGCastApiAvailable, s = setTimeout(() => t(null), C);
17
+ const e = l.__onGCastApiAvailable, s = setTimeout(() => t(null), w);
17
18
  if (l.__onGCastApiAvailable = (i, a) => {
18
19
  e == null || e(i, a), clearTimeout(s), t(i ? b() : null);
19
20
  }, !document.querySelector('script[src*="cast_sender.js"]')) {
20
21
  const i = document.createElement("script");
21
- i.async = !0, i.src = T, i.onerror = () => {
22
+ i.async = !0, i.src = C, i.onerror = () => {
22
23
  clearTimeout(s), g = null, t(null);
23
24
  }, document.head.appendChild(i);
24
25
  }
25
26
  }), g);
26
27
  }
27
- const I = ["paused", "currentTime", "duration", "ended", "volume", "muted", "readyState", "seeking", "buffered", "play", "pause"], M = {
28
+ const M = ["paused", "currentTime", "duration", "ended", "volume", "muted", "readyState", "seeking", "buffered", "play", "pause"], P = {
28
29
  length: 0,
29
30
  start: () => {
30
31
  throw new DOMException("Index out of range", "IndexSizeError");
@@ -32,11 +33,11 @@ const I = ["paused", "currentTime", "duration", "ended", "volume", "muted", "rea
32
33
  end: () => {
33
34
  throw new DOMException("Index out of range", "IndexSizeError");
34
35
  }
35
- }, P = 150;
36
- function A(l, t) {
36
+ }, N = 150;
37
+ function k(l, t) {
37
38
  return Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, t).get.call(l);
38
39
  }
39
- class N {
40
+ class B {
40
41
  constructor(t, e, s) {
41
42
  r(this, "state");
42
43
  r(this, "pendingSeek", null);
@@ -53,7 +54,7 @@ class N {
53
54
  const t = this.video, e = () => this.state, s = (i, a) => {
54
55
  Object.defineProperty(t, i, { configurable: !0, enumerable: !1, ...a });
55
56
  };
56
- s("paused", { get: () => e().paused }), s("ended", { get: () => e().ended }), s("duration", { get: () => e().duration }), s("readyState", { get: () => 4 }), s("seeking", { get: () => this.pendingSeek !== null }), s("buffered", { get: () => M }), s("currentTime", {
57
+ s("paused", { get: () => e().paused }), s("ended", { get: () => e().ended }), s("duration", { get: () => e().duration }), s("readyState", { get: () => 4 }), s("seeking", { get: () => this.pendingSeek !== null }), s("buffered", { get: () => P }), s("currentTime", {
57
58
  get: () => this.pendingSeek ?? e().currentTime,
58
59
  set: (i) => this.seek(i)
59
60
  }), s("volume", {
@@ -74,7 +75,7 @@ class N {
74
75
  uninstall() {
75
76
  if (this.installed) {
76
77
  this.installed = !1, this.seekTimer && clearTimeout(this.seekTimer), this.seekTimer = null, this.pendingSeek = null;
77
- for (const t of I) delete this.video[t];
78
+ for (const t of M) delete this.video[t];
78
79
  }
79
80
  }
80
81
  /** TV'den gelen durum — değişen alanlar için olay yayar. */
@@ -90,15 +91,15 @@ class N {
90
91
  this.seekTimer = null;
91
92
  const i = this.pendingSeek ?? e;
92
93
  this.commands.seek(i), this.state = { ...this.state, currentTime: i, ended: !1 }, this.pendingSeek = null, this.fire("seeked"), this.fire("timeupdate");
93
- }, P);
94
+ }, N);
94
95
  }
95
96
  fire(t) {
96
97
  this.video.dispatchEvent(new Event(t));
97
98
  }
98
99
  }
99
- let y = null, m = null;
100
- const B = 20, _ = 5;
101
- class L {
100
+ let v = null, p = null;
101
+ const _ = 20, L = 5;
102
+ class R {
102
103
  constructor(t, e) {
103
104
  r(this, "options");
104
105
  r(this, "api", null);
@@ -125,7 +126,7 @@ class L {
125
126
  });
126
127
  r(this, "onSessionState", (t) => {
127
128
  const e = t.sessionState;
128
- (e === "SESSION_STARTED" || e === "SESSION_RESUMED") && t.session ? y === this ? (y = null, this.attach(t.session, !0)) : e === "SESSION_RESUMED" && !m && this.tryResume(t.session) : (e === "SESSION_ENDED" || e === "SESSION_START_FAILED") && (y === this && (y = null), m === this && this.detach());
129
+ (e === "SESSION_STARTED" || e === "SESSION_RESUMED") && t.session ? v === this ? (v = null, this.attach(t.session, !0)) : e === "SESSION_RESUMED" && !p && this.tryResume(t.session) : (e === "SESSION_ENDED" || e === "SESSION_START_FAILED") && (v === this && (v = null), p === this && this.detach());
129
130
  });
130
131
  r(this, "onRemoteChange", (t) => {
131
132
  var i;
@@ -154,7 +155,7 @@ class L {
154
155
  (i = this.overlay) == null || i.toggleAttribute("data-break", !!t.value);
155
156
  break;
156
157
  case "isConnected":
157
- !t.value && m === this && this.detach();
158
+ !t.value && p === this && this.detach();
158
159
  break;
159
160
  }
160
161
  });
@@ -190,7 +191,7 @@ class L {
190
191
  if (this.castBtn) return;
191
192
  const { btn: t, icon: e } = this.button(this.ctx.i18n.castButton, "cast", () => this.requestCast());
192
193
  t.setAttribute("part", "cast-button"), this.castBtn = t, this.castIcon = e;
193
- const s = await w();
194
+ const s = await I();
194
195
  if (!s || this.destroyed) {
195
196
  s || this.ctx.log({ message: "Google Cast is not available in this browser (Chrome / Edge over HTTPS needed)" });
196
197
  return;
@@ -204,7 +205,7 @@ class L {
204
205
  const a = s.framework.CastContextEventType;
205
206
  i.addEventListener(a.CAST_STATE_CHANGED, this.onCastState), i.addEventListener(a.SESSION_STATE_CHANGED, this.onSessionState), this.onCastState({ castState: i.getCastState() });
206
207
  const n = i.getCurrentSession();
207
- n && !m && this.tryResume(n);
208
+ n && !p && this.tryResume(n);
208
209
  }
209
210
  requestCast() {
210
211
  if (this.context) {
@@ -212,8 +213,8 @@ class L {
212
213
  this.ctx.log({ message: "Cast: wait for the ad to finish" });
213
214
  return;
214
215
  }
215
- y = this, this.context.requestSession().catch((t) => {
216
- y === this && (y = null), String(t) !== "cancel" && this.ctx.log({ message: `Cast session failed: ${String(t)}` });
216
+ v = this, this.context.requestSession().catch((t) => {
217
+ v === this && (v = null), String(t) !== "cancel" && this.ctx.log({ message: `Cast session failed: ${String(t)}` });
217
218
  });
218
219
  }
219
220
  }
@@ -223,30 +224,30 @@ class L {
223
224
  e && s && s === e.src && this.attach(t, !1);
224
225
  }
225
226
  async attach(t, e) {
226
- var p, c, h, u;
227
+ var y, d, u, m;
227
228
  const s = this.api;
228
229
  if (!s || this.destroyed) return;
229
- m && m !== this && m.detach(), m = this, this.session = t;
230
- const i = this.ctx.videoEl, a = A(i, "currentTime"), n = A(i, "duration");
230
+ p && p !== this && p.detach(), p = this, this.session = t;
231
+ const i = this.ctx.videoEl, a = k(i, "currentTime"), n = k(i, "duration");
231
232
  HTMLMediaElement.prototype.pause.call(i), this.savedAutoplay = i.autoplay, i.autoplay = !1;
232
- const o = new s.framework.RemotePlayer(), d = new s.framework.RemotePlayerController(o);
233
- this.player = o, this.controller = d, this.proxy = new N(
233
+ const o = new s.framework.RemotePlayer(), c = new s.framework.RemotePlayerController(o);
234
+ this.player = o, this.controller = c, this.proxy = new B(
234
235
  i,
235
236
  {
236
- play: () => o.isPaused && d.playOrPause(),
237
- pause: () => !o.isPaused && d.playOrPause(),
237
+ play: () => o.isPaused && c.playOrPause(),
238
+ pause: () => !o.isPaused && c.playOrPause(),
238
239
  seek: (f) => {
239
- o.currentTime = f, d.seek();
240
+ o.currentTime = f, c.seek();
240
241
  },
241
242
  setVolume: (f) => {
242
- o.volumeLevel = f, d.setVolumeLevel();
243
+ o.volumeLevel = f, c.setVolumeLevel();
243
244
  },
244
- setMuted: (f) => o.isMuted !== f && d.muteOrUnmute()
245
+ setMuted: (f) => o.isMuted !== f && c.muteOrUnmute()
245
246
  },
246
247
  { paused: !1, currentTime: a, duration: n, volume: i.volume, muted: i.muted, ended: !1 }
247
- ), this.proxy.install(), d.addEventListener(s.framework.RemotePlayerEventType.ANY_CHANGE, this.onRemoteChange), i.addEventListener("loadstart", this.onLocalSourceChange), this.ctx.onRemoteChange(!0);
248
- const v = ((p = t.getCastDevice()) == null ? void 0 : p.friendlyName) || this.ctx.i18n.castDeviceFallback;
249
- this.showOverlay(this.ctx.i18n.castPlayingOn.replace("{device}", v)), (c = this.castBtn) == null || c.setAttribute("aria-pressed", "true"), this.castIcon && E(this.castIcon, "cast-connected"), this.emit("connected", "chromecast", v), e ? await this.loadMedia(a, !0) : (this.loadedSrc = ((u = (h = t.getMediaSession()) == null ? void 0 : h.media) == null ? void 0 : u.contentId) ?? "", this.loadedContent = this.ctx.contentKey());
248
+ ), this.proxy.install(), c.addEventListener(s.framework.RemotePlayerEventType.ANY_CHANGE, this.onRemoteChange), i.addEventListener("loadstart", this.onLocalSourceChange), this.ctx.onRemoteChange(!0);
249
+ const h = ((y = t.getCastDevice()) == null ? void 0 : y.friendlyName) || this.ctx.i18n.castDeviceFallback;
250
+ this.showOverlay(this.ctx.i18n.castPlayingOn.replace("{device}", h)), (d = this.castBtn) == null || d.setAttribute("aria-pressed", "true"), this.castIcon && E(this.castIcon, "cast-connected"), this.emit("connected", "chromecast", h), e ? await this.loadMedia(a, !0) : (this.loadedSrc = ((m = (u = t.getMediaSession()) == null ? void 0 : u.media) == null ? void 0 : m.contentId) ?? "", this.loadedContent = this.ctx.contentKey());
250
251
  }
251
252
  /** O an çalan içeriği TV'ye yükler (reklam araları ve altyazılarla). */
252
253
  async loadMedia(t, e) {
@@ -257,19 +258,19 @@ class L {
257
258
  }
258
259
  const n = s.chrome.media, o = new n.MediaInfo(a.src, a.contentType);
259
260
  o.streamType = a.live ? n.StreamType.LIVE : n.StreamType.BUFFERED;
260
- const d = a.music ? new n.MusicTrackMediaMetadata() : new n.GenericMediaMetadata();
261
- d.title = a.title, a.music ? d.artist = a.subtitle : d.subtitle = a.subtitle, a.image && (d.images = [new s.chrome.Image(a.image)]), o.metadata = d, /mpegurl/i.test(a.contentType) && this.options.hlsSegmentFormat === "fmp4" && (n.HlsSegmentFormat && (o.hlsSegmentFormat = n.HlsSegmentFormat.FMP4), n.HlsVideoSegmentFormat && (o.hlsVideoSegmentFormat = n.HlsVideoSegmentFormat.FMP4));
262
- const v = [];
263
- o.tracks = a.subtitles.map((c, h) => {
264
- const u = new n.Track(h + 1, n.TrackType.TEXT);
265
- return u.trackContentId = c.src, u.trackContentType = "text/vtt", u.subtype = n.TextTrackType.SUBTITLES, u.name = c.label, u.language = c.lang, c.default && v.push(h + 1), u;
261
+ const c = a.music ? new n.MusicTrackMediaMetadata() : new n.GenericMediaMetadata();
262
+ c.title = a.title, a.music ? c.artist = a.subtitle : c.subtitle = a.subtitle, a.image && (c.images = [new s.chrome.Image(a.image)]), o.metadata = c, /mpegurl/i.test(a.contentType) && this.options.hlsSegmentFormat === "fmp4" && (n.HlsSegmentFormat && (o.hlsSegmentFormat = n.HlsSegmentFormat.FMP4), n.HlsVideoSegmentFormat && (o.hlsVideoSegmentFormat = n.HlsVideoSegmentFormat.FMP4));
263
+ const h = [];
264
+ o.tracks = a.subtitles.map((d, u) => {
265
+ const m = new n.Track(u + 1, n.TrackType.TEXT);
266
+ return m.trackContentId = d.src, m.trackContentType = "text/vtt", m.subtype = n.TextTrackType.SUBTITLES, m.name = d.label, m.language = d.lang, d.default && h.push(u + 1), m;
266
267
  }), this.applyAds(o, a);
267
- const p = new n.LoadRequest(o);
268
- p.currentTime = a.live ? void 0 : t, p.autoplay = e, v.length && (p.activeTrackIds = v), this.loadedSrc = a.src, this.loadedContent = this.ctx.contentKey();
268
+ const y = new n.LoadRequest(o);
269
+ y.currentTime = a.live ? void 0 : t, y.autoplay = e, h.length && (y.activeTrackIds = h), this.loadedSrc = a.src, this.loadedContent = this.ctx.contentKey();
269
270
  try {
270
- await i.loadMedia(p), this.ctx.log({ message: "Cast: media loaded on the TV", details: { src: a.src, ads: a.ads ? a.ads.vmap ? "vmap" : "vast" : "none" } });
271
- } catch (c) {
272
- this.ctx.log({ message: `Cast: the TV could not load the media: ${String(c)}`, fatal: !0, details: { src: a.src } });
271
+ await i.loadMedia(y), this.ctx.log({ message: "Cast: media loaded on the TV", details: { src: a.src, ads: a.ads ? a.ads.vmap ? "vmap" : "vast" : "none" } });
272
+ } catch (d) {
273
+ this.ctx.log({ message: `Cast: the TV could not load the media: ${String(d)}`, fatal: !0, details: { src: a.src } });
273
274
  }
274
275
  }
275
276
  /**
@@ -277,32 +278,35 @@ class L {
277
278
  * ara olarak eklenir — preroll (0), aralıklı midroll'lar, postroll (-1). Reklamları receiver oynatır ve sayar.
278
279
  */
279
280
  applyAds(t, e) {
280
- var p;
281
+ var y;
281
282
  const s = e.ads, i = this.api.chrome.media;
282
283
  if (!s) return;
283
284
  if (s.vmap) {
284
- const c = new i.VastAdsRequest();
285
- c.adTagUrl = s.vmap, t.vmapAdsRequest = c;
285
+ const d = new i.VastAdsRequest();
286
+ d.adTagUrl = s.vmap, t.vmapAdsRequest = d;
286
287
  return;
287
288
  }
288
- const a = [], n = [], o = (c, h, u) => {
289
- const f = new i.BreakClip(`clip-${c}`), S = new i.VastAdsRequest();
290
- S.adTagUrl = h, f.vastAdsRequest = S, a.push(f), n.push(new i.Break(`break-${c}`, [`clip-${c}`], u));
289
+ const a = [], n = [], o = (d, u, m) => {
290
+ const f = new i.BreakClip(`clip-${d}`), S = new i.VastAdsRequest();
291
+ S.adTagUrl = u, f.vastAdsRequest = S, a.push(f), n.push(new i.Break(`break-${d}`, [`clip-${d}`], m));
291
292
  };
292
293
  s.preroll && o("pre", s.preroll, 0);
293
- const d = s.midrollIntervalSeconds ?? 0, v = ((p = this.proxy) == null ? void 0 : p.current.duration) ?? NaN;
294
- if (s.midroll && d > 0 && !e.live && Number.isFinite(v))
295
- for (let c = d, h = 1; c < v - _ && h <= B; c += d, h++) o(`mid-${h}`, s.midroll, c);
294
+ const c = s.midrollIntervalSeconds ?? 0, h = ((y = this.proxy) == null ? void 0 : y.current.duration) ?? NaN;
295
+ if (s.midroll && c > 0 && !e.live && Number.isFinite(h))
296
+ for (let d = c, u = 1; d < h - L && u <= _; d += c, u++) o(`mid-${u}`, s.midroll, d);
296
297
  s.postroll && !e.live && o("post", s.postroll, -1), a.length && (t.breakClips = a, t.breaks = n);
297
298
  }
298
299
  detach() {
299
- var n, o;
300
+ var c, h;
300
301
  const t = this.proxy;
301
302
  if (!t) return;
302
- m === this && (m = null);
303
+ p === this && (p = null);
303
304
  const { currentTime: e, paused: s, ended: i } = t.current, a = this.ctx.videoEl;
304
- (n = this.controller) == null || n.removeEventListener(this.api.framework.RemotePlayerEventType.ANY_CHANGE, this.onRemoteChange), a.removeEventListener("loadstart", this.onLocalSourceChange), t.uninstall(), this.proxy = null, this.player = null, this.controller = null, this.session = null, this.loadedSrc = "", a.autoplay = this.savedAutoplay, this.ctx.onRemoteChange(!1), this.hideOverlay(), (o = this.castBtn) == null || o.setAttribute("aria-pressed", "false"), this.castIcon && E(this.castIcon, "cast"), Number.isFinite(e) && e > 0 && !i && (a.currentTime = e), !s && !i && a.play().catch(() => {
305
- }), this.emit("disconnected", "chromecast");
305
+ (c = this.controller) == null || c.removeEventListener(this.api.framework.RemotePlayerEventType.ANY_CHANGE, this.onRemoteChange), a.removeEventListener("loadstart", this.onLocalSourceChange), t.uninstall(), this.proxy = null, this.player = null, this.controller = null, this.session = null, this.loadedSrc = "", a.autoplay = this.savedAutoplay, this.ctx.onRemoteChange(!1), this.hideOverlay(), (h = this.castBtn) == null || h.setAttribute("aria-pressed", "false"), this.castIcon && E(this.castIcon, "cast");
306
+ const n = Number.isFinite(e) && e > 0 && !i ? e : null, o = () => {
307
+ n !== null && T(a, n, { guardMs: 2e3 });
308
+ };
309
+ !s && !i ? a.play().then(o, o) : o(), this.emit("disconnected", "chromecast");
306
310
  }
307
311
  // ── AirPlay (Safari) ────────────────────────────────────────────────────
308
312
  initAirPlay() {
@@ -369,7 +373,7 @@ class L {
369
373
  }
370
374
  destroy() {
371
375
  var t, e, s, i, a;
372
- if (this.destroyed = !0, m === this && this.detach(), y === this && (y = null), this.context && this.api) {
376
+ if (this.destroyed = !0, p === this && this.detach(), v === this && (v = null), this.context && this.api) {
373
377
  const n = this.api.framework.CastContextEventType;
374
378
  this.context.removeEventListener(n.CAST_STATE_CHANGED, this.onCastState), this.context.removeEventListener(n.SESSION_STATE_CHANGED, this.onSessionState);
375
379
  }
@@ -377,11 +381,11 @@ class L {
377
381
  })), (e = this.castBtn) == null || e.remove(), (s = this.airplayBtn) == null || s.remove(), (i = this.remoteBtn) == null || i.remove(), (a = this.overlay) == null || a.remove();
378
382
  }
379
383
  }
380
- function D(l, t) {
381
- return new L(l, t);
384
+ function F(l, t) {
385
+ return new R(l, t);
382
386
  }
383
387
  export {
384
- L as CastController,
385
- D as installCast
388
+ R as CastController,
389
+ F as installCast
386
390
  };
387
- //# sourceMappingURL=index-Miba3PD_.js.map
391
+ //# sourceMappingURL=cast-bMrkGGuD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cast-bMrkGGuD.js","sources":["../../src/plugins/cast/castSdk.ts","../../src/plugins/cast/RemoteMediaProxy.ts","../../src/plugins/cast/CastController.ts","../../src/plugins/cast/index.ts"],"sourcesContent":["/**\n * Google Cast Web Sender SDK (CAF) — kullanılan yüzeyin minimal tipleri ve yükleyicisi.\n * https://developers.google.com/cast/docs/web_sender\n */\n\nexport interface CastImage {\n url: string;\n}\n\nexport interface CastMediaMetadata {\n metadataType?: number;\n title?: string;\n subtitle?: string;\n artist?: string;\n albumName?: string;\n images?: CastImage[];\n}\n\nexport interface CastTrack {\n trackContentId?: string;\n trackContentType?: string;\n subtype?: string;\n name?: string;\n language?: string;\n}\n\nexport interface CastVastAdsRequest {\n adTagUrl?: string;\n}\n\nexport interface CastBreakClip {\n vastAdsRequest?: CastVastAdsRequest;\n}\n\nexport interface CastMediaInfo {\n contentId: string;\n contentType: string;\n streamType?: string;\n metadata?: CastMediaMetadata;\n tracks?: CastTrack[];\n hlsSegmentFormat?: string;\n hlsVideoSegmentFormat?: string;\n vmapAdsRequest?: CastVastAdsRequest;\n breakClips?: CastBreakClip[];\n breaks?: unknown[];\n}\n\nexport interface CastLoadRequest {\n currentTime?: number;\n autoplay?: boolean;\n activeTrackIds?: number[];\n}\n\nexport interface CastSessionLike {\n loadMedia(request: CastLoadRequest): Promise<unknown>;\n getCastDevice(): { friendlyName?: string };\n getMediaSession(): { media?: { contentId?: string } } | null;\n}\n\nexport interface RemotePlayerLike {\n isConnected: boolean;\n isMediaLoaded: boolean;\n isPaused: boolean;\n currentTime: number;\n duration: number;\n volumeLevel: number;\n isMuted: boolean;\n playerState: string | null;\n isPlayingBreak: boolean;\n}\n\nexport interface RemotePlayerControllerLike {\n addEventListener(type: string, fn: (e: { field: string; value: unknown }) => void): void;\n removeEventListener(type: string, fn: (e: { field: string; value: unknown }) => void): void;\n playOrPause(): void;\n seek(): void;\n setVolumeLevel(): void;\n muteOrUnmute(): void;\n stop(): void;\n}\n\nexport interface CastContextLike {\n setOptions(options: Record<string, unknown>): void;\n addEventListener(type: string, fn: (e: { castState?: string; sessionState?: string; session?: CastSessionLike }) => void): void;\n removeEventListener(type: string, fn: (e: { castState?: string; sessionState?: string; session?: CastSessionLike }) => void): void;\n requestSession(): Promise<unknown>;\n getCurrentSession(): CastSessionLike | null;\n getCastState(): string;\n endCurrentSession(stopCasting: boolean): void;\n}\n\ntype Ctor<T> = new (...args: never[]) => T;\n\n/** `window.cast.framework` + `window.chrome.cast` — yalnızca kullandıklarımız. */\nexport interface CastApi {\n framework: {\n CastContext: { getInstance(): CastContextLike };\n CastContextEventType: { CAST_STATE_CHANGED: string; SESSION_STATE_CHANGED: string };\n RemotePlayer: Ctor<RemotePlayerLike>;\n RemotePlayerController: new (player: RemotePlayerLike) => RemotePlayerControllerLike;\n RemotePlayerEventType: { ANY_CHANGE: string };\n };\n chrome: {\n AutoJoinPolicy: { ORIGIN_SCOPED: string };\n media: {\n DEFAULT_MEDIA_RECEIVER_APP_ID: string;\n MediaInfo: new (contentId: string, contentType: string) => CastMediaInfo;\n GenericMediaMetadata: Ctor<CastMediaMetadata>;\n MusicTrackMediaMetadata: Ctor<CastMediaMetadata>;\n LoadRequest: new (media: CastMediaInfo) => CastLoadRequest;\n Track: new (trackId: number, type: string) => CastTrack;\n TrackType: { TEXT: string };\n TextTrackType: { SUBTITLES: string };\n StreamType: { BUFFERED: string; LIVE: string };\n VastAdsRequest: Ctor<CastVastAdsRequest>;\n BreakClip: new (id: string) => CastBreakClip;\n Break: new (id: string, breakClipIds: string[], position: number) => unknown;\n HlsSegmentFormat?: { TS: string; FMP4: string; AAC: string };\n HlsVideoSegmentFormat?: { MPEG2_TS: string; FMP4: string };\n };\n Image: new (url: string) => CastImage;\n };\n}\n\nconst CAST_SDK_SRC = 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1';\nconst LOAD_TIMEOUT_MS = 10_000;\nlet loading: Promise<CastApi | null> | null = null;\n\nfunction current(): CastApi | null {\n const w = window as unknown as { cast?: { framework?: CastApi['framework'] }; chrome?: { cast?: CastApi['chrome'] } };\n return w.cast?.framework && w.chrome?.cast ? { framework: w.cast.framework, chrome: w.chrome.cast } : null;\n}\n\n/**\n * Cast SDK'yı bir kez yükler. Yalnızca Chromium tarayıcılarda (Chrome / Edge) ve güvenli bağlamda (HTTPS) denenir;\n * diğerlerinde ya da SDK \"Cast yok\" derse null — buton hiç görünmez.\n */\nexport function loadCastSdk(): Promise<CastApi | null> {\n if (loading) return loading;\n const w = window as unknown as { chrome?: unknown; __onGCastApiAvailable?: (available: boolean, reason?: string) => void };\n if (current()) return (loading = Promise.resolve(current()));\n if (!w.chrome || !window.isSecureContext) return (loading = Promise.resolve(null));\n loading = new Promise<CastApi | null>((resolve) => {\n const previous = w.__onGCastApiAvailable;\n const timer = setTimeout(() => resolve(null), LOAD_TIMEOUT_MS);\n // SDK hazır olunca bu global geri çağrıyı çağırır — sayfa kendi kurduysa onu da çağır.\n w.__onGCastApiAvailable = (available, reason) => {\n previous?.(available, reason);\n clearTimeout(timer);\n resolve(available ? current() : null);\n };\n if (!document.querySelector('script[src*=\"cast_sender.js\"]')) {\n const s = document.createElement('script');\n s.async = true;\n s.src = CAST_SDK_SRC;\n s.onerror = () => {\n clearTimeout(timer);\n loading = null;\n resolve(null);\n };\n document.head.appendChild(s);\n }\n });\n return loading;\n}\n","/** Uzak oynatıcıya (TV) giden komutlar. */\nexport interface RemoteCommands {\n play(): void;\n pause(): void;\n seek(time: number): void;\n setVolume(volume: number): void;\n setMuted(muted: boolean): void;\n}\n\nexport interface RemoteState {\n paused: boolean;\n currentTime: number;\n duration: number;\n volume: number;\n muted: boolean;\n ended: boolean;\n}\n\nconst PROXIED = ['paused', 'currentTime', 'duration', 'ended', 'volume', 'muted', 'readyState', 'seeking', 'buffered', 'play', 'pause'] as const;\nconst EMPTY_RANGES: TimeRanges = {\n length: 0,\n start: () => {\n throw new DOMException('Index out of range', 'IndexSizeError');\n },\n end: () => {\n throw new DOMException('Index out of range', 'IndexSizeError');\n },\n};\n/** Seek bar sürüklenirken her harekette TV'ye istek gitmesin. */\nconst SEEK_DEBOUNCE_MS = 150;\n\n/** <video>'nun gerçek (prototip) değeri — vekil kuruluyken de. */\nexport function nativeGet<K extends 'currentTime' | 'duration' | 'paused' | 'ended'>(video: HTMLVideoElement, key: K): HTMLMediaElement[K] {\n const d = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, key);\n return d!.get!.call(video) as HTMLMediaElement[K];\n}\n\n/**\n * Cast sırasında `<video>` örneğinin oynatma yüzeyini (paused, currentTime, play(), volume…) TV'ye bağlar ve TV'den\n * gelen durumu olay olarak (play / pause / timeupdate / volumechange…) yayar. Böylece kontrol çubuğu, seek bar,\n * klavye kısayolları ve eklentiler hiç değişmeden TV'yi yönetir. Kaldırılınca örnek özellikleri silinir, prototip\n * (gerçek video) geri gelir.\n */\nexport class RemoteMediaProxy {\n private state: RemoteState;\n private pendingSeek: number | null = null;\n private seekTimer: ReturnType<typeof setTimeout> | null = null;\n private installed = false;\n\n constructor(\n private readonly video: HTMLVideoElement,\n private readonly commands: RemoteCommands,\n initial: RemoteState\n ) {\n this.state = { ...initial };\n }\n\n get current(): Readonly<RemoteState> {\n return this.state;\n }\n\n install(): void {\n if (this.installed) return;\n this.installed = true;\n const v = this.video;\n const s = (): RemoteState => this.state;\n const define = (key: string, desc: PropertyDescriptor): void => {\n Object.defineProperty(v, key, { configurable: true, enumerable: false, ...desc });\n };\n define('paused', { get: () => s().paused });\n define('ended', { get: () => s().ended });\n define('duration', { get: () => s().duration });\n define('readyState', { get: () => 4 });\n define('seeking', { get: () => this.pendingSeek !== null });\n define('buffered', { get: () => EMPTY_RANGES });\n define('currentTime', {\n get: () => this.pendingSeek ?? s().currentTime,\n set: (t: number) => this.seek(t),\n });\n define('volume', {\n get: () => s().volume,\n set: (vol: number) => {\n const clamped = Math.min(1, Math.max(0, Number(vol) || 0));\n this.state.volume = clamped;\n this.commands.setVolume(clamped);\n this.fire('volumechange');\n },\n });\n define('muted', {\n get: () => s().muted,\n set: (m: boolean) => {\n this.state.muted = !!m;\n this.commands.setMuted(!!m);\n this.fire('volumechange');\n },\n });\n define('play', {\n value: () => {\n if (this.state.ended) this.seek(0);\n this.commands.play();\n return Promise.resolve();\n },\n });\n define('pause', { value: () => this.commands.pause() });\n }\n\n uninstall(): void {\n if (!this.installed) return;\n this.installed = false;\n if (this.seekTimer) clearTimeout(this.seekTimer);\n this.seekTimer = null;\n this.pendingSeek = null;\n for (const key of PROXIED) delete (this.video as unknown as Record<string, unknown>)[key];\n }\n\n /** TV'den gelen durum — değişen alanlar için olay yayar. */\n update(patch: Partial<RemoteState>): void {\n const prev = this.state;\n this.state = { ...prev, ...patch };\n const next = this.state;\n if (patch.duration !== undefined && patch.duration !== prev.duration) this.fire('durationchange');\n if (patch.currentTime !== undefined && patch.currentTime !== prev.currentTime && this.pendingSeek === null) this.fire('timeupdate');\n if (patch.volume !== undefined || patch.muted !== undefined) {\n if (next.volume !== prev.volume || next.muted !== prev.muted) this.fire('volumechange');\n }\n if (patch.paused !== undefined && patch.paused !== prev.paused) {\n if (next.paused) this.fire('pause');\n else {\n this.fire('play');\n this.fire('playing');\n }\n }\n if (patch.ended && !prev.ended) this.fire('ended');\n }\n\n private seek(t: number): void {\n const target = Math.max(0, Number(t) || 0);\n const first = this.pendingSeek === null;\n this.pendingSeek = target;\n if (first) this.fire('seeking');\n this.fire('timeupdate');\n if (this.seekTimer) clearTimeout(this.seekTimer);\n this.seekTimer = setTimeout(() => {\n this.seekTimer = null;\n const to = this.pendingSeek ?? target;\n this.commands.seek(to);\n this.state = { ...this.state, currentTime: to, ended: false };\n this.pendingSeek = null;\n this.fire('seeked');\n this.fire('timeupdate');\n }, SEEK_DEBOUNCE_MS);\n }\n\n private fire(type: string): void {\n this.video.dispatchEvent(new Event(type));\n }\n}\n","import type { CastOptions } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\nimport { setIconName } from '../../icons/Icon';\nimport { loadCastSdk, type CastApi, type CastContextLike, type CastMediaInfo, type CastSessionLike, type RemotePlayerControllerLike, type RemotePlayerLike } from './castSdk';\nimport { RemoteMediaProxy, nativeGet } from './RemoteMediaProxy';\nimport { seekWhenReady } from '../shared/seekWhenReady';\n\n/** TV'ye gönderilecek içerik — player o anki duruma göre hazırlar. */\nexport interface CastMedia {\n src: string;\n contentType: string;\n live: boolean;\n title?: string;\n subtitle?: string;\n image?: string;\n /** Ses modu: TV'de müzik parçası olarak (kapak, sanatçı). */\n music: boolean;\n subtitles: Array<{ src: string; label: string; lang: string; default?: boolean }>;\n /** TV'de oynatılacak reklamlar (makroları doldurulmuş tag'ler); null = reklamsız. */\n ads: { vmap?: string; preroll?: string; midroll?: string; midrollIntervalSeconds?: number; postroll?: string } | null;\n}\n\nexport interface CastPlayerContext {\n hostEl: HTMLElement;\n videoEl: HTMLVideoElement;\n overlayEl: HTMLElement;\n i18n: HopeLocaleStrings;\n log(entry: { message: string; fatal?: boolean; details?: Record<string, string | number | boolean | undefined> }): void;\n addButton(label: string, icon: string, onClick: () => void): { btn: HTMLButtonElement; icon: HTMLElement };\n getMedia(): CastMedia | null;\n /** Yerelde video reklamı oynuyor — bu sırada yayın başlatılmaz. */\n isAdPlaying(): boolean;\n /** hls.js (MSE) ile oynatılıyor — AirPlay / Remote Playback bu kaynağı TV'ye veremez. */\n isMse(): boolean;\n /** İçerik kimliği — kalite / yedek kaynak değişimi aynı içerik sayılır (TV'de konum korunur). */\n contentKey(): string;\n /** İçerik TV'de mi (Chromecast) — player yerel reklamları askıya alır, otomatik oynatmayı keser. */\n onRemoteChange(remote: boolean): void;\n}\n\ntype Via = 'chromecast' | 'airplay' | 'remote';\ntype CastState = 'available' | 'unavailable' | 'connecting' | 'connected' | 'disconnected';\n\n/** Aynı sayfada birden çok player: Cast oturumu, butonuna basılan player'ındır. */\nlet requester: CastController | null = null;\nlet owner: CastController | null = null;\n/** Midroll aralığından üretilecek en fazla ara. */\nconst MAX_INTERVAL_BREAKS = 20;\nconst MIDROLL_END_MARGIN_S = 5;\n\n/**\n * TV'ye yayın: Google Cast (Chromecast / Google TV), AirPlay ve Remote Playback API. Her biri ayrı ayrı açılır;\n * butonlar yalnızca uygun cihaz varken görünür. Chromecast'te içerik TV'de oynar, player kumandaya dönüşür\n * (RemoteMediaProxy); bağlantı bitince yerelde TV'deki saniyeden devam eder.\n */\nexport class CastController {\n private options: CastOptions;\n private api: CastApi | null = null;\n private context: CastContextLike | null = null;\n private session: CastSessionLike | null = null;\n private player: RemotePlayerLike | null = null;\n private controller: RemotePlayerControllerLike | null = null;\n private proxy: RemoteMediaProxy | null = null;\n private castBtn: HTMLButtonElement | null = null;\n private castIcon: HTMLElement | null = null;\n private airplayBtn: HTMLButtonElement | null = null;\n private remoteBtn: HTMLButtonElement | null = null;\n private overlay: HTMLDivElement | null = null;\n private loadedSrc = '';\n private loadedContent = '';\n private savedAutoplay = false;\n private airplayActive = false;\n private destroyed = false;\n private remoteWatchId: number | null = null;\n\n constructor(\n private readonly ctx: CastPlayerContext,\n options: CastOptions\n ) {\n this.options = options;\n if (options.chromecast) void this.initChromecast();\n if (options.airplay) this.initAirPlay();\n if (options.remotePlayback) this.initRemotePlayback();\n }\n\n update(options: CastOptions): void {\n const prev = this.options;\n this.options = options;\n if (options.chromecast && !prev.chromecast) void this.initChromecast();\n if (options.airplay && !prev.airplay) this.initAirPlay();\n if (options.remotePlayback && !prev.remotePlayback) this.initRemotePlayback();\n if (this.castBtn) this.castBtn.hidden = !options.chromecast || this.castBtn.hidden;\n if (this.airplayBtn && !options.airplay) this.airplayBtn.hidden = true;\n if (this.remoteBtn && !options.remotePlayback) this.remoteBtn.hidden = true;\n }\n\n /** İçerik şu an TV'de mi (herhangi bir yoldan). */\n get casting(): boolean {\n return !!this.proxy || this.airplayActive || this.ctx.videoEl.remote?.state === 'connected';\n }\n\n private emit(state: CastState, via: Via, device?: string): void {\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:cast', { detail: { state, via, device } }));\n }\n\n private button(label: string, icon: string, onClick: () => void): { btn: HTMLButtonElement; icon: HTMLElement } {\n const b = this.ctx.addButton(label, icon, onClick);\n b.btn.hidden = true;\n return b;\n }\n\n // ── Google Cast ─────────────────────────────────────────────────────────\n\n private async initChromecast(): Promise<void> {\n if (this.castBtn) return;\n const { btn, icon } = this.button(this.ctx.i18n.castButton, 'cast', () => this.requestCast());\n btn.setAttribute('part', 'cast-button');\n this.castBtn = btn;\n this.castIcon = icon;\n const api = await loadCastSdk();\n if (!api || this.destroyed) {\n if (!api) this.ctx.log({ message: 'Google Cast is not available in this browser (Chrome / Edge over HTTPS needed)' });\n return;\n }\n this.api = api;\n const context = api.framework.CastContext.getInstance();\n this.context = context;\n context.setOptions({\n receiverApplicationId: this.options.receiverAppId || api.chrome.media.DEFAULT_MEDIA_RECEIVER_APP_ID,\n autoJoinPolicy: api.chrome.AutoJoinPolicy.ORIGIN_SCOPED,\n });\n const types = api.framework.CastContextEventType;\n context.addEventListener(types.CAST_STATE_CHANGED, this.onCastState);\n context.addEventListener(types.SESSION_STATE_CHANGED, this.onSessionState);\n this.onCastState({ castState: context.getCastState() });\n // Sayfa yenilendi ve oturum sürüyor (TV aynı içeriği oynatıyor) → kumandayı yeniden bağla.\n const existing = context.getCurrentSession();\n if (existing && !owner) this.tryResume(existing);\n }\n\n private readonly onCastState = (e: { castState?: string }): void => {\n const state = e.castState ?? 'NO_DEVICES_AVAILABLE';\n if (this.castBtn) this.castBtn.hidden = state === 'NO_DEVICES_AVAILABLE';\n this.castBtn?.toggleAttribute('data-connecting', state === 'CONNECTING');\n if (!this.proxy) this.emit(state === 'NO_DEVICES_AVAILABLE' ? 'unavailable' : state === 'CONNECTING' ? 'connecting' : 'available', 'chromecast');\n };\n\n private readonly onSessionState = (e: { sessionState?: string; session?: CastSessionLike }): void => {\n const s = e.sessionState;\n if ((s === 'SESSION_STARTED' || s === 'SESSION_RESUMED') && e.session) {\n if (requester === this) {\n requester = null;\n void this.attach(e.session, true);\n } else if (s === 'SESSION_RESUMED' && !owner) {\n this.tryResume(e.session);\n }\n } else if (s === 'SESSION_ENDED' || s === 'SESSION_START_FAILED') {\n if (requester === this) requester = null;\n if (owner === this) this.detach();\n }\n };\n\n private requestCast(): void {\n if (!this.context) return;\n if (this.ctx.isAdPlaying()) {\n this.ctx.log({ message: 'Cast: wait for the ad to finish' });\n return;\n }\n requester = this;\n // Bağlıyken Chrome'un seçicisi \"yayını durdur\"u da sunar.\n this.context.requestSession().catch((err: unknown) => {\n if (requester === this) requester = null;\n // Kullanıcı seçiciyi kapattı ('cancel') — hata değil.\n if (String(err) !== 'cancel') this.ctx.log({ message: `Cast session failed: ${String(err)}` });\n });\n }\n\n private tryResume(session: CastSessionLike): void {\n const media = this.ctx.getMedia();\n const remoteId = session.getMediaSession()?.media?.contentId;\n if (media && remoteId && remoteId === media.src) void this.attach(session, false);\n }\n\n private async attach(session: CastSessionLike, load: boolean): Promise<void> {\n const api = this.api;\n if (!api || this.destroyed) return;\n if (owner && owner !== this) owner.detach();\n owner = this;\n this.session = session;\n const v = this.ctx.videoEl;\n const startAt = nativeGet(v, 'currentTime');\n const duration = nativeGet(v, 'duration');\n HTMLMediaElement.prototype.pause.call(v);\n // Cast sırasında kaynak değişirse (playlist / kalite) yerel video kendiliğinden çalmasın.\n this.savedAutoplay = v.autoplay;\n v.autoplay = false;\n\n const player = new api.framework.RemotePlayer();\n const controller = new api.framework.RemotePlayerController(player);\n this.player = player;\n this.controller = controller;\n this.proxy = new RemoteMediaProxy(\n v,\n {\n play: () => player.isPaused && controller.playOrPause(),\n pause: () => !player.isPaused && controller.playOrPause(),\n seek: (t) => {\n player.currentTime = t;\n controller.seek();\n },\n setVolume: (vol) => {\n player.volumeLevel = vol;\n controller.setVolumeLevel();\n },\n setMuted: (m) => player.isMuted !== m && controller.muteOrUnmute(),\n },\n { paused: false, currentTime: startAt, duration, volume: v.volume, muted: v.muted, ended: false }\n );\n this.proxy.install();\n controller.addEventListener(api.framework.RemotePlayerEventType.ANY_CHANGE, this.onRemoteChange);\n v.addEventListener('loadstart', this.onLocalSourceChange);\n this.ctx.onRemoteChange(true);\n const device = session.getCastDevice()?.friendlyName || this.ctx.i18n.castDeviceFallback;\n this.showOverlay(this.ctx.i18n.castPlayingOn.replace('{device}', device));\n this.castBtn?.setAttribute('aria-pressed', 'true');\n if (this.castIcon) setIconName(this.castIcon, 'cast-connected');\n this.emit('connected', 'chromecast', device);\n if (load) await this.loadMedia(startAt, true);\n else {\n this.loadedSrc = session.getMediaSession()?.media?.contentId ?? '';\n this.loadedContent = this.ctx.contentKey();\n }\n }\n\n /** O an çalan içeriği TV'ye yükler (reklam araları ve altyazılarla). */\n private async loadMedia(currentTime: number, autoplay: boolean): Promise<void> {\n const api = this.api;\n const session = this.session;\n const media = this.ctx.getMedia();\n if (!api || !session || !media) {\n this.ctx.log({ message: 'Cast: nothing to send (no playable source)' });\n return;\n }\n const m = api.chrome.media;\n const info: CastMediaInfo = new m.MediaInfo(media.src, media.contentType);\n info.streamType = media.live ? m.StreamType.LIVE : m.StreamType.BUFFERED;\n const md = media.music ? new m.MusicTrackMediaMetadata() : new m.GenericMediaMetadata();\n md.title = media.title;\n if (media.music) md.artist = media.subtitle;\n else md.subtitle = media.subtitle;\n if (media.image) md.images = [new api.chrome.Image(media.image)];\n info.metadata = md;\n if (/mpegurl/i.test(media.contentType) && this.options.hlsSegmentFormat === 'fmp4') {\n if (m.HlsSegmentFormat) info.hlsSegmentFormat = m.HlsSegmentFormat.FMP4;\n if (m.HlsVideoSegmentFormat) info.hlsVideoSegmentFormat = m.HlsVideoSegmentFormat.FMP4;\n }\n const activeTrackIds: number[] = [];\n info.tracks = media.subtitles.map((s, i) => {\n const t = new m.Track(i + 1, m.TrackType.TEXT);\n t.trackContentId = s.src;\n t.trackContentType = 'text/vtt';\n t.subtype = m.TextTrackType.SUBTITLES;\n t.name = s.label;\n t.language = s.lang;\n if (s.default) activeTrackIds.push(i + 1);\n return t;\n });\n this.applyAds(info, media);\n const req = new m.LoadRequest(info);\n req.currentTime = media.live ? undefined : currentTime;\n req.autoplay = autoplay;\n if (activeTrackIds.length) req.activeTrackIds = activeTrackIds;\n this.loadedSrc = media.src;\n this.loadedContent = this.ctx.contentKey();\n try {\n await session.loadMedia(req);\n this.ctx.log({ message: 'Cast: media loaded on the TV', details: { src: media.src, ads: media.ads ? (media.ads.vmap ? 'vmap' : 'vast') : 'none' } });\n } catch (err) {\n this.ctx.log({ message: `Cast: the TV could not load the media: ${String(err)}`, fatal: true, details: { src: media.src } });\n }\n }\n\n /**\n * Reklamlar TV'de: VMAP verilmişse receiver tüm araları kendisi planlar (vmapAdsRequest); yoksa VAST tag'leri\n * ara olarak eklenir — preroll (0), aralıklı midroll'lar, postroll (-1). Reklamları receiver oynatır ve sayar.\n */\n private applyAds(info: CastMediaInfo, media: CastMedia): void {\n const ads = media.ads;\n const m = this.api!.chrome.media;\n if (!ads) return;\n if (ads.vmap) {\n const req = new m.VastAdsRequest();\n req.adTagUrl = ads.vmap;\n info.vmapAdsRequest = req;\n return;\n }\n const clips: unknown[] = [];\n const breaks: unknown[] = [];\n const add = (id: string, tag: string, position: number): void => {\n const clip = new m.BreakClip(`clip-${id}`);\n const req = new m.VastAdsRequest();\n req.adTagUrl = tag;\n clip.vastAdsRequest = req;\n clips.push(clip);\n breaks.push(new m.Break(`break-${id}`, [`clip-${id}`], position));\n };\n if (ads.preroll) add('pre', ads.preroll, 0);\n const every = ads.midrollIntervalSeconds ?? 0;\n const duration = this.proxy?.current.duration ?? NaN;\n if (ads.midroll && every > 0 && !media.live && Number.isFinite(duration)) {\n // Bitişe çok yakın midroll olmasın (orada postroll var).\n for (let t = every, i = 1; t < duration - MIDROLL_END_MARGIN_S && i <= MAX_INTERVAL_BREAKS; t += every, i++) add(`mid-${i}`, ads.midroll, t);\n }\n if (ads.postroll && !media.live) add('post', ads.postroll, -1);\n if (clips.length) {\n info.breakClips = clips as CastMediaInfo['breakClips'];\n info.breaks = breaks;\n }\n }\n\n private readonly onRemoteChange = (e: { field: string; value: unknown }): void => {\n const p = this.player;\n const proxy = this.proxy;\n if (!p || !proxy) return;\n switch (e.field) {\n case 'isPaused':\n proxy.update({ paused: !!e.value });\n break;\n case 'currentTime':\n proxy.update({ currentTime: Number(e.value) || 0 });\n break;\n case 'duration':\n proxy.update({ duration: Number(e.value) > 0 ? Number(e.value) : proxy.current.duration });\n break;\n case 'volumeLevel':\n proxy.update({ volume: Number(e.value) });\n break;\n case 'isMuted':\n proxy.update({ muted: !!e.value });\n break;\n case 'playerState':\n // İçerik TV'de bitti (IDLE + daha önce oynuyordu) → ended.\n if (e.value === 'IDLE' && p.isMediaLoaded === false && proxy.current.currentTime > 0) proxy.update({ ended: true, paused: true });\n else if (e.value === 'PLAYING') proxy.update({ ended: false, paused: false });\n break;\n case 'isPlayingBreak':\n this.overlay?.toggleAttribute('data-break', !!e.value);\n break;\n case 'isConnected':\n if (!e.value && owner === this) this.detach();\n break;\n }\n };\n\n /** Cast sırasında player başka bir kaynağa geçti (playlist sonraki öğe, kalite, yedek kaynak) → TV'ye de gönder. */\n private readonly onLocalSourceChange = (): void => {\n if (!this.proxy) return;\n HTMLMediaElement.prototype.pause.call(this.ctx.videoEl);\n const media = this.ctx.getMedia();\n if (!media || media.src === this.loadedSrc) return;\n // Aynı içeriğin başka kalitesi / yedeği ise kaldığı yerden, yeni bir içerikse (playlist) baştan.\n const same = this.ctx.contentKey() === this.loadedContent;\n void this.loadMedia(same ? this.proxy.current.currentTime : 0, true);\n };\n\n private detach(): void {\n const proxy = this.proxy;\n if (!proxy) return;\n if (owner === this) owner = null;\n const { currentTime, paused, ended } = proxy.current;\n const v = this.ctx.videoEl;\n this.controller?.removeEventListener(this.api!.framework.RemotePlayerEventType.ANY_CHANGE, this.onRemoteChange);\n v.removeEventListener('loadstart', this.onLocalSourceChange);\n proxy.uninstall();\n this.proxy = null;\n this.player = null;\n this.controller = null;\n this.session = null;\n this.loadedSrc = '';\n v.autoplay = this.savedAutoplay;\n this.ctx.onRemoteChange(false);\n this.hideOverlay();\n this.castBtn?.setAttribute('aria-pressed', 'false');\n if (this.castIcon) setIconName(this.castIcon, 'cast');\n // TV'deki saniyeden yerelde devam (bittiyse olduğu yerde kalır).\n // Sıra önemli: önce oynat, SONRA sar. WebKitGTK / WPE (GStreamer) duraklatılmışken yapılan sarmayı play()'de\n // kaybediyor (sona fırlıyor ya da takılıyor); oynarken yapılan sarma her motorda tutuyor.\n const seekTo = Number.isFinite(currentTime) && currentTime > 0 && !ended ? currentTime : null;\n const seek = () => {\n if (seekTo !== null) seekWhenReady(v, seekTo, { guardMs: 2000 });\n };\n if (!paused && !ended) void v.play().then(seek, seek);\n else seek();\n this.emit('disconnected', 'chromecast');\n }\n\n // ── AirPlay (Safari) ────────────────────────────────────────────────────\n\n private initAirPlay(): void {\n if (this.airplayBtn || !('WebKitPlaybackTargetAvailabilityEvent' in window)) return;\n const v = this.ctx.videoEl as HTMLVideoElement & { webkitShowPlaybackTargetPicker?: () => void; webkitCurrentPlaybackTargetIsWireless?: boolean };\n v.setAttribute('x-webkit-airplay', 'allow');\n const { btn } = this.button(this.ctx.i18n.airplayButton, 'airplay', () => {\n if (this.ctx.isMse()) {\n this.ctx.log({ message: 'AirPlay: this source plays through hls.js (MSE) — use hls.engine: \"auto\" / \"native\" on Safari for AirPlay' });\n return;\n }\n v.webkitShowPlaybackTargetPicker?.();\n });\n btn.setAttribute('part', 'airplay-button');\n this.airplayBtn = btn;\n v.addEventListener('webkitplaybacktargetavailabilitychanged', ((e: Event & { availability?: string }) => {\n const available = e.availability === 'available';\n btn.hidden = !available || !this.options.airplay;\n if (!this.airplayActive) this.emit(available ? 'available' : 'unavailable', 'airplay');\n }) as EventListener);\n v.addEventListener('webkitcurrentplaybacktargetiswirelesschanged', () => {\n const on = !!v.webkitCurrentPlaybackTargetIsWireless;\n if (on === this.airplayActive) return;\n this.airplayActive = on;\n btn.setAttribute('aria-pressed', String(on));\n if (on) this.showOverlay(this.ctx.i18n.airplayPlaying);\n else this.hideOverlay();\n this.emit(on ? 'connected' : 'disconnected', 'airplay');\n });\n }\n\n // ── Remote Playback API ─────────────────────────────────────────────────\n\n private initRemotePlayback(): void {\n const v = this.ctx.videoEl;\n const remote = v.remote;\n if (this.remoteBtn || !remote) return;\n v.disableRemotePlayback = false;\n const { btn } = this.button(this.ctx.i18n.castButton, 'cast', () => {\n if (this.ctx.isMse()) {\n this.ctx.log({ message: 'Remote playback: hls.js (MSE) sources cannot be sent to the device' });\n return;\n }\n remote.prompt().catch((err: unknown) => this.ctx.log({ message: `Remote playback: ${String(err)}` }));\n });\n btn.setAttribute('part', 'remote-playback-button');\n this.remoteBtn = btn;\n remote\n .watchAvailability((available) => {\n // Google Cast butonu görünüyorsa aynı işi yapan ikinci butonu gösterme.\n btn.hidden = !available || this.ctx.isMse() || !!(this.castBtn && !this.castBtn.hidden);\n if (remote.state === 'disconnected') this.emit(available ? 'available' : 'unavailable', 'remote');\n })\n .then((id) => (this.remoteWatchId = id))\n .catch(() => (btn.hidden = true));\n remote.addEventListener('connecting', () => this.emit('connecting', 'remote'));\n remote.addEventListener('connect', () => {\n btn.setAttribute('aria-pressed', 'true');\n this.showOverlay(this.ctx.i18n.castPlayingOn.replace('{device}', this.ctx.i18n.castDeviceFallback));\n this.emit('connected', 'remote');\n });\n remote.addEventListener('disconnect', () => {\n btn.setAttribute('aria-pressed', 'false');\n this.hideOverlay();\n this.emit('disconnected', 'remote');\n });\n }\n\n // ── \"TV'de oynatılıyor\" katmanı ─────────────────────────────────────────\n\n private showOverlay(text: string): void {\n if (!this.overlay) {\n const el = document.createElement('div');\n el.className = 'hp-cast-overlay';\n el.setAttribute('part', 'cast-overlay');\n el.setAttribute('role', 'status');\n const icon = document.createElement('i');\n icon.className = 'hp-icon hp-icon-cast-connected';\n icon.setAttribute('aria-hidden', 'true');\n const label = document.createElement('span');\n label.className = 'hp-cast-overlay-text';\n const ad = document.createElement('span');\n ad.className = 'hp-cast-overlay-ad';\n el.append(icon, label, ad);\n this.ctx.overlayEl.appendChild(el);\n this.overlay = el;\n }\n this.overlay.querySelector('.hp-cast-overlay-text')!.textContent = text;\n this.overlay.querySelector('.hp-cast-overlay-ad')!.textContent = this.ctx.i18n.castAdOnTv;\n this.overlay.removeAttribute('data-break');\n this.overlay.setAttribute('data-open', '');\n this.ctx.overlayEl.setAttribute('data-casting', '');\n }\n\n private hideOverlay(): void {\n this.overlay?.removeAttribute('data-open');\n this.ctx.overlayEl.removeAttribute('data-casting');\n }\n\n refreshLabels(): void {\n this.castBtn?.setAttribute('aria-label', this.ctx.i18n.castButton);\n this.airplayBtn?.setAttribute('aria-label', this.ctx.i18n.airplayButton);\n this.remoteBtn?.setAttribute('aria-label', this.ctx.i18n.castButton);\n }\n\n destroy(): void {\n this.destroyed = true;\n if (owner === this) {\n // Player sayfadan kalkıyor: TV'deki yayın sürsün (Cast'in olağan davranışı), kumanda bağı kopsun.\n this.detach();\n }\n if (requester === this) requester = null;\n if (this.context && this.api) {\n const types = this.api.framework.CastContextEventType;\n this.context.removeEventListener(types.CAST_STATE_CHANGED, this.onCastState);\n this.context.removeEventListener(types.SESSION_STATE_CHANGED, this.onSessionState);\n }\n if (this.remoteWatchId !== null) void this.ctx.videoEl.remote?.cancelWatchAvailability(this.remoteWatchId).catch(() => {});\n this.castBtn?.remove();\n this.airplayBtn?.remove();\n this.remoteBtn?.remove();\n this.overlay?.remove();\n }\n}\n","import { CastController, type CastMedia, type CastPlayerContext } from './CastController';\nimport type { CastOptions } from '../../types';\n\n/** TV'ye yayını kurar (Google Cast / AirPlay / Remote Playback — her biri seçenekle açılır). */\nexport function installCast(ctx: CastPlayerContext, options: CastOptions): CastController {\n return new CastController(ctx, options);\n}\n\nexport { CastController };\nexport type { CastMedia, CastPlayerContext };\n"],"names":["CAST_SDK_SRC","LOAD_TIMEOUT_MS","loading","current","w","_a","_b","loadCastSdk","resolve","previous","timer","available","reason","s","PROXIED","EMPTY_RANGES","SEEK_DEBOUNCE_MS","nativeGet","video","key","RemoteMediaProxy","commands","initial","__publicField","v","define","desc","t","vol","clamped","m","patch","prev","next","target","first","to","type","requester","owner","MAX_INTERVAL_BREAKS","MIDROLL_END_MARGIN_S","CastController","ctx","options","e","state","p","proxy","media","same","via","device","label","icon","onClick","b","btn","api","context","types","existing","err","session","remoteId","load","startAt","duration","player","controller","setIconName","_d","_c","currentTime","autoplay","info","md","activeTrackIds","i","req","ads","clips","breaks","add","id","tag","position","clip","every","paused","ended","seekTo","seek","seekWhenReady","on","remote","text","el","ad","_e","installCast"],"mappings":"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"}
@@ -71,4 +71,4 @@ export {
71
71
  o as CountdownScreen,
72
72
  p as installCountdownScreen
73
73
  };
74
- //# sourceMappingURL=index-rENB3n9O.js.map
74
+ //# sourceMappingURL=countdownScreen-CI-u6jjA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"countdownScreen-CI-u6jjA.js","sources":["../../src/plugins/countdown-screen/CountdownScreen.ts","../../src/plugins/countdown-screen/index.ts"],"sourcesContent":["import type { CountdownScreenOptions } from '../../types';\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\n\n/** Hedef tarihe kadar içeriği engelleyen geri sayım ekranı (blockChrome ile). */\nexport class CountdownScreen {\n private readonly wrapper: HTMLElement;\n private readonly timerLabel: HTMLElement;\n private readonly timerEl: HTMLElement;\n private interval: ReturnType<typeof setInterval> | null = null;\n private bgInterval: ReturnType<typeof setInterval> | null = null;\n private imageIndex = 0;\n private readonly targetTime: number;\n private resolved = false;\n private readonly completeCallbacks: Array<() => void> = [];\n\n constructor(\n private readonly ctx: GatePlayerContext,\n private readonly options: CountdownScreenOptions\n ) {\n this.targetTime = new Date(options.time).getTime();\n\n this.wrapper = document.createElement('div');\n this.wrapper.setAttribute('part', 'countdown-screen');\n this.wrapper.className =\n 'hp:absolute hp:inset-0 hp:z-40 hp:flex hp:items-end hp:bg-cover hp:bg-center hp:bg-surface hp:text-on-surface';\n\n const info = document.createElement('div');\n info.className = 'hp:p-4 hp:w-full hp:bg-gradient-to-t hp:from-black/80 hp:to-transparent';\n\n if (options.title) {\n const title = document.createElement('h3');\n title.className = 'hp:text-lg hp:font-semibold hp:m-0';\n title.textContent = options.title;\n info.appendChild(title);\n }\n if (options.spot) {\n const spot = document.createElement('p');\n spot.className = 'hp:text-sm hp:opacity-80 hp:m-0 hp:mt-1';\n spot.textContent = options.spot;\n info.appendChild(spot);\n }\n if (options.description) {\n const desc = document.createElement('p');\n desc.className = 'hp:text-xs hp:opacity-70 hp:m-0 hp:mt-1';\n desc.textContent = options.description;\n info.appendChild(desc);\n }\n\n this.timerLabel = document.createElement('span');\n this.timerLabel.className = 'hp:text-xs hp:opacity-70 hp:block hp:mt-2';\n this.timerLabel.textContent = ctx.i18n.countdownRemaining;\n info.appendChild(this.timerLabel);\n\n this.timerEl = document.createElement('div');\n this.timerEl.className = 'hp:text-2xl hp:font-mono hp:tabular-nums';\n info.appendChild(this.timerEl);\n\n this.wrapper.appendChild(info);\n this.updateBackground();\n ctx.overlayContainerEl.appendChild(this.wrapper);\n\n ctx.blockChrome();\n ctx.videoEl.addEventListener('play', this.onPlayWhileBlocked);\n\n if (Array.isArray(options.coverImage) && options.coverImage.length > 0) {\n this.bgInterval = setInterval(() => {\n this.imageIndex = (this.imageIndex + 1) % (options.coverImage as string[]).length;\n this.updateBackground();\n }, options.imageChangeInterval ?? 5000);\n }\n\n this.start();\n }\n\n refreshLabels(): void {\n this.timerLabel.textContent = this.ctx.i18n.countdownRemaining;\n }\n\n isComplete(): boolean {\n return this.resolved;\n }\n\n /** Geri sayım bitince çağrılır (zaten bittiyse anında). */\n onComplete(cb: () => void): void {\n if (this.resolved) cb();\n else this.completeCallbacks.push(cb);\n }\n\n destroy(): void {\n if (this.interval) clearInterval(this.interval);\n if (this.bgInterval) clearInterval(this.bgInterval);\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\n if (!this.resolved) this.ctx.unblockChrome();\n this.wrapper.remove();\n this.completeCallbacks.length = 0;\n }\n\n private readonly onPlayWhileBlocked = (): void => {\n if (!this.resolved) this.ctx.videoEl.pause();\n };\n\n private updateBackground(): void {\n const img = Array.isArray(this.options.coverImage) ? this.options.coverImage[this.imageIndex] : this.options.coverImage;\n this.wrapper.style.backgroundImage = img ? `url(\"${img}\")` : 'none';\n }\n\n private start(): void {\n const tick = () => {\n const diff = Math.max(this.targetTime - Date.now(), 0);\n const h = Math.floor(diff / 3600000);\n const m = Math.floor((diff / 60000) % 60);\n const s = Math.floor((diff / 1000) % 60);\n this.timerEl.textContent = `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;\n\n if (diff <= 0) this.complete();\n };\n\n tick();\n if (this.targetTime - Date.now() > 0) {\n this.interval = setInterval(tick, 1000);\n } else {\n this.complete();\n }\n }\n\n private complete(): void {\n if (this.resolved) return;\n this.resolved = true;\n if (this.interval) clearInterval(this.interval);\n if (this.bgInterval) clearInterval(this.bgInterval);\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\n this.wrapper.remove();\n this.ctx.unblockChrome();\n const callbacks = this.completeCallbacks.splice(0);\n for (const cb of callbacks) cb();\n }\n}\n","import { CountdownScreen } from './CountdownScreen';\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\nimport type { CountdownScreenOptions } from '../../types';\n\nexport function installCountdownScreen(ctx: GatePlayerContext, options: CountdownScreenOptions): CountdownScreen {\n return new CountdownScreen(ctx, options);\n}\n\nexport { CountdownScreen };\nexport type { GatePlayerContext };\n"],"names":["CountdownScreen","ctx","options","__publicField","info","title","spot","desc","cb","img","tick","diff","h","m","callbacks","installCountdownScreen"],"mappings":"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"}
@@ -107,4 +107,4 @@ export {
107
107
  E as DaiController,
108
108
  v as installDai
109
109
  };
110
- //# sourceMappingURL=index-Q8FMOHj0.js.map
110
+ //# sourceMappingURL=dai-B9Tth1Iv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dai-B9Tth1Iv.js","sources":["../../src/plugins/dai/loadDaiSdk.ts","../../src/plugins/dai/DaiController.ts","../../src/plugins/dai/index.ts"],"sourcesContent":["const DAI_SDK_URL = 'https://imasdk.googleapis.com/js/sdkloader/ima3_dai.js';\n\n// Window.google loadImaSdk.ts'de zaten augment edildi — burada tekrar tanımlanmıyor.\nfunction getLoadedDai(): typeof google.ima.dai | undefined {\n return (window as unknown as { google?: { ima?: { dai?: typeof google.ima.dai } } }).google?.ima?.dai;\n}\n\nlet loadPromise: Promise<typeof google.ima.dai> | null = null;\n\n/** DAI SDK, normal IMA SDK'dan (loadImaSdk.ts) AYRI bir script — ima3_dai.js. */\nexport function loadDaiSdk(): Promise<typeof google.ima.dai> {\n const existing = getLoadedDai();\n if (existing) return Promise.resolve(existing);\n if (loadPromise) return loadPromise;\n\n loadPromise = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = DAI_SDK_URL;\n script.async = true;\n script.onload = () => {\n const dai = getLoadedDai();\n if (dai) resolve(dai);\n else reject(new Error('DAI SDK yüklendi ama window.google.ima.dai yok'));\n };\n script.onerror = () => reject(new Error('DAI SDK yüklenemedi (reklam engelleyici olabilir)'));\n document.head.appendChild(script);\n });\n return loadPromise;\n}\n","import { loadDaiSdk } from './loadDaiSdk';\nimport type { DaiOptions } from '../../types';\n\nexport interface DaiPlayerContext {\n videoEl: HTMLVideoElement;\n hostEl: HTMLElement;\n /** IMA DAI'nin kendi ad UI'ını (skip/countdown/clickthrough) çizdiği katman — plugins/ads'teki adLayerEl ile aynı fikir. */\n adUiEl: HTMLElement;\n loadStreamUrl(url: string): Promise<void>;\n /** Reklam arası boyunca kullanıcı canlı reklamın İÇİNE seek edemesin diye. */\n disableSeeking(): void;\n enableSeeking(): void;\n}\n\n/** Google IMA DAI: stream StreamManager üzerinden istenir; reklam araları sırasında seek kilitlenir. */\nexport class DaiController {\n private dai: typeof google.ima.dai | null = null;\n private streamManager: google.ima.dai.api.StreamManager | null = null;\n private readonly metadataTrackListeners = new Map<TextTrack, () => void>();\n\n constructor(\n private readonly ctx: DaiPlayerContext,\n private readonly options: DaiOptions\n ) {}\n\n async install(): Promise<void> {\n let dai: typeof google.ima.dai;\n try {\n dai = await loadDaiSdk();\n } catch (err) {\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:aderror', { detail: { message: String(err) } }));\n if (this.options.fallbackStreamUrl) void this.ctx.loadStreamUrl(this.options.fallbackStreamUrl);\n return;\n }\n this.dai = dai;\n\n this.streamManager = new dai.api.StreamManager(this.ctx.videoEl, this.ctx.adUiEl);\n this.streamManager.addEventListener(\n [\n dai.api.StreamEvent.Type.LOADED,\n dai.api.StreamEvent.Type.ERROR,\n dai.api.StreamEvent.Type.AD_BREAK_STARTED,\n dai.api.StreamEvent.Type.AD_BREAK_ENDED,\n ],\n this.onStreamEvent\n );\n\n const request = new dai.api.LiveStreamRequest();\n request.assetKey = this.options.assetKey;\n if (this.options.apiKey) request.apiKey = this.options.apiKey;\n if (this.options.adTagParameters) request.adTagParameters = this.options.adTagParameters;\n\n this.attachMetadataForwarding();\n this.streamManager.requestStream(request);\n }\n\n destroy(): void {\n this.ctx.videoEl.textTracks.removeEventListener('addtrack', this.onAddTrack);\n for (const [track, listener] of this.metadataTrackListeners) track.removeEventListener('cuechange', listener);\n this.metadataTrackListeners.clear();\n this.streamManager?.reset();\n }\n\n private readonly onStreamEvent = (event: google.ima.dai.api.StreamEvent): void => {\n if (!this.dai) return;\n const Type = this.dai.api.StreamEvent.Type;\n\n switch (event.type) {\n case Type.LOADED: {\n const { url } = event.getStreamData();\n void this.ctx.loadStreamUrl(url).then(() => void this.ctx.videoEl.play().catch(() => {}));\n break;\n }\n case Type.ERROR: {\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:aderror', { detail: { message: 'DAI stream error' } }));\n if (this.options.fallbackStreamUrl) void this.ctx.loadStreamUrl(this.options.fallbackStreamUrl);\n break;\n }\n case Type.AD_BREAK_STARTED:\n this.ctx.disableSeeking();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:adstart', { detail: { type: 'midroll' } }));\n break;\n case Type.AD_BREAK_ENDED:\n this.ctx.enableSeeking();\n this.ctx.hostEl.dispatchEvent(new CustomEvent('hp:adend', { detail: { type: 'midroll' } }));\n break;\n default:\n break;\n }\n };\n\n /** HLS live DAI reklam zamanlaması ID3/timed-metadata ile gelir — StreamManager.processMetadata()'ya iletilir. */\n private attachMetadataForwarding(): void {\n for (let i = 0; i < this.ctx.videoEl.textTracks.length; i++) {\n this.listenMetadataTrack(this.ctx.videoEl.textTracks[i]!);\n }\n this.ctx.videoEl.textTracks.addEventListener('addtrack', this.onAddTrack);\n }\n\n private readonly onAddTrack = (e: TrackEvent): void => {\n if (e.track instanceof TextTrack) this.listenMetadataTrack(e.track);\n };\n\n private listenMetadataTrack(track: TextTrack): void {\n if (track.kind !== 'metadata' || this.metadataTrackListeners.has(track)) return;\n track.mode = 'hidden';\n\n const listener = () => {\n const cues = track.activeCues;\n if (!cues || !this.streamManager) return;\n for (let i = 0; i < cues.length; i++) {\n const cue = cues[i] as unknown as { value?: unknown; startTime?: number };\n if (cue.value === undefined) continue;\n try {\n this.streamManager.processMetadata('ID3', cue.value as Uint8Array | string, cue.startTime);\n } catch {\n /* DAI akışla ilgisiz bir metadata cue'su olabilir — yoksay */\n }\n }\n };\n track.addEventListener('cuechange', listener);\n this.metadataTrackListeners.set(track, listener);\n }\n}\n","import { DaiController, type DaiPlayerContext } from './DaiController';\nimport type { DaiOptions } from '../../types';\n\nexport async function installDai(ctx: DaiPlayerContext, options: DaiOptions): Promise<DaiController> {\n const controller = new DaiController(ctx, options);\n await controller.install();\n return controller;\n}\n\nexport { DaiController };\nexport type { DaiPlayerContext };\n"],"names":["DAI_SDK_URL","getLoadedDai","_a","_b","loadPromise","loadDaiSdk","existing","resolve","reject","script","dai","DaiController","ctx","options","__publicField","event","Type","url","e","err","request","track","listener","i","cues","cue","installDai","controller"],"mappings":"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"}
@@ -105,4 +105,4 @@ export {
105
105
  x as DebugPanel,
106
106
  f as installDebugPanel
107
107
  };
108
- //# sourceMappingURL=index-DCXX1ZJG.js.map
108
+ //# sourceMappingURL=debugPanel-Bnc_7GOn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debugPanel-Bnc_7GOn.js","sources":["../../src/plugins/debug/DebugPanel.ts","../../src/plugins/debug/index.ts"],"sourcesContent":["import type { HopeLocaleStrings } from '../../i18n/types';\nimport type { ErrorLog, PlayerLogEntry, PlayerLogSource } from '../../debug/ErrorLog';\n\nexport interface DebugPanelContext {\n containerEl: HTMLElement;\n i18n: HopeLocaleStrings;\n log: ErrorLog;\n version: string;\n}\n\nconst CLOSE_ICON =\n '<svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6L6 18\"/></svg>';\n\n/**\n * Sağ tık menüsündeki \"Hata ayıklama\" — player'ın tüm hatalarını (medya, yayın, reklam, altyazı) zaman sırasıyla,\n * ayrıntılarıyla gösteren ve tüm player alanını kaplayan pencere. Uzun satırlar (URL'ler) kırılır, liste kendi içinde\n * kayar; yeni hata gelince açık pencere canlı güncellenir.\n */\nexport class DebugPanel {\n private readonly el: HTMLDivElement;\n private readonly titleEl: HTMLSpanElement;\n private readonly countEl: HTMLSpanElement;\n private readonly copyBtn: HTMLButtonElement;\n private readonly clearBtn: HTMLButtonElement;\n private readonly closeBtn: HTMLButtonElement;\n private readonly list: HTMLOListElement;\n private readonly emptyEl: HTMLParagraphElement;\n private copiedTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private readonly ctx: DebugPanelContext) {\n this.el = document.createElement('div');\n this.el.className = 'hp-debug';\n this.el.setAttribute('part', 'debug-panel');\n this.el.setAttribute('role', 'dialog');\n // Odak pencerenin kendisinde (ESC ile kapanır) — butona odaklanınca ipucu kendiliğinden açılıyordu.\n this.el.tabIndex = -1;\n\n const header = document.createElement('div');\n header.className = 'hp-debug-header';\n const title = document.createElement('div');\n title.className = 'hp-debug-title';\n this.titleEl = document.createElement('span');\n this.countEl = document.createElement('span');\n this.countEl.className = 'hp-debug-count';\n title.append(this.titleEl, this.countEl);\n\n const actions = document.createElement('div');\n actions.className = 'hp-debug-actions';\n this.copyBtn = this.button('hp-debug-btn', () => void this.copy());\n this.clearBtn = this.button('hp-debug-btn', () => this.ctx.log.clear());\n this.closeBtn = this.button('hp-stats-close', () => this.hide());\n this.closeBtn.innerHTML = CLOSE_ICON;\n actions.append(this.copyBtn, this.clearBtn, this.closeBtn);\n header.append(title, actions);\n\n this.list = document.createElement('ol');\n this.list.className = 'hp-debug-list';\n this.emptyEl = document.createElement('p');\n this.emptyEl.className = 'hp-debug-empty';\n\n this.el.append(header, this.list, this.emptyEl);\n // Panel tıklamaları / kaydırma videoyu oynat-duraklat yapmasın, klavye kısayolları tetiklenmesin.\n this.el.addEventListener('pointerdown', (e) => e.stopPropagation());\n this.el.addEventListener('click', (e) => e.stopPropagation());\n this.el.addEventListener('dblclick', (e) => e.stopPropagation());\n this.el.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') this.hide();\n e.stopPropagation();\n });\n this.refreshLabels();\n }\n\n get isVisible(): boolean {\n return this.el.isConnected;\n }\n\n show(): void {\n if (!this.isVisible) this.ctx.containerEl.appendChild(this.el);\n this.ctx.log.onChange = () => this.render();\n this.render();\n this.el.focus({ preventScroll: true });\n }\n\n hide(): void {\n if (this.ctx.log.onChange) this.ctx.log.onChange = null;\n this.el.remove();\n }\n\n refreshLabels(): void {\n const t = this.ctx.i18n;\n this.titleEl.textContent = t.debugTitle;\n this.copyBtn.textContent = t.debugCopy;\n this.clearBtn.textContent = t.debugClear;\n this.closeBtn.setAttribute('aria-label', t.debugClose);\n this.emptyEl.textContent = t.debugEmpty;\n if (this.isVisible) this.render();\n }\n\n destroy(): void {\n if (this.copiedTimer) clearTimeout(this.copiedTimer);\n this.hide();\n }\n\n private button(className: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = className;\n btn.addEventListener('click', onClick);\n return btn;\n }\n\n private sourceLabel(source: PlayerLogSource): string {\n const t = this.ctx.i18n;\n return { media: t.debugSourceMedia, stream: t.debugSourceStream, ads: t.debugSourceAds, subtitles: t.debugSourceSubtitles, player: t.debugSourcePlayer }[source];\n }\n\n private render(): void {\n const entries = this.ctx.log.entries;\n this.countEl.textContent = entries.length ? String(entries.length) : '';\n this.emptyEl.hidden = entries.length > 0;\n this.clearBtn.disabled = entries.length === 0;\n this.copyBtn.disabled = entries.length === 0;\n // En yeni en üstte.\n this.list.replaceChildren(...[...entries].reverse().map((e) => this.row(e)));\n }\n\n private row(entry: PlayerLogEntry): HTMLLIElement {\n const li = document.createElement('li');\n li.className = 'hp-debug-row';\n if (entry.fatal) li.setAttribute('data-fatal', '');\n\n const head = document.createElement('div');\n head.className = 'hp-debug-row-head';\n const time = document.createElement('time');\n time.className = 'hp-debug-time';\n const d = new Date(entry.time);\n time.textContent = `${d.toLocaleTimeString([], { hour12: false })}.${String(d.getMilliseconds()).padStart(3, '0')}`;\n const source = document.createElement('span');\n source.className = 'hp-debug-source';\n source.setAttribute('data-source', entry.source);\n source.textContent = this.sourceLabel(entry.source);\n head.append(time, source);\n if (entry.fatal) {\n const fatal = document.createElement('span');\n fatal.className = 'hp-debug-fatal';\n fatal.textContent = this.ctx.i18n.debugFatal;\n head.appendChild(fatal);\n }\n\n const message = document.createElement('div');\n message.className = 'hp-debug-message';\n message.textContent = entry.message;\n if (entry.count && entry.count > 1) {\n const repeat = document.createElement('span');\n repeat.className = 'hp-debug-repeat';\n repeat.textContent = ` ×${entry.count}`;\n message.appendChild(repeat);\n }\n li.append(head, message);\n\n const details = Object.entries(entry.details ?? {}).filter(([, v]) => v !== undefined && v !== '');\n if (details.length) {\n const dl = document.createElement('dl');\n dl.className = 'hp-debug-details';\n for (const [k, v] of details) {\n const dt = document.createElement('dt');\n dt.textContent = k;\n const dd = document.createElement('dd');\n dd.textContent = String(v);\n dl.append(dt, dd);\n }\n li.appendChild(dl);\n }\n return li;\n }\n\n private async copy(): Promise<void> {\n const text = `HopeCorePlayer ${this.ctx.version} · ${navigator.userAgent}\\n${this.ctx.log.toText()}`;\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n return;\n }\n this.copyBtn.textContent = this.ctx.i18n.debugCopied;\n if (this.copiedTimer) clearTimeout(this.copiedTimer);\n this.copiedTimer = setTimeout(() => {\n this.copiedTimer = null;\n this.copyBtn.textContent = this.ctx.i18n.debugCopy;\n }, 1500);\n }\n}\n","import { DebugPanel, type DebugPanelContext } from './DebugPanel';\n\nexport function installDebugPanel(ctx: DebugPanelContext): DebugPanel {\n return new DebugPanel(ctx);\n}\n\nexport { DebugPanel };\nexport type { DebugPanelContext };\n"],"names":["CLOSE_ICON","DebugPanel","ctx","__publicField","header","title","actions","e","className","onClick","btn","source","t","entries","entry","li","head","time","d","fatal","message","repeat","details","v","dl","k","dt","dd","text","installDebugPanel"],"mappings":"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"}
@@ -49,4 +49,4 @@ export {
49
49
  u as Dubbing,
50
50
  d as installDubbing
51
51
  };
52
- //# sourceMappingURL=index-DXWK4EFa.js.map
52
+ //# sourceMappingURL=dubbing-kNMPpyHl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dubbing-kNMPpyHl.js","sources":["../../src/plugins/dubbing/Dubbing.ts","../../src/plugins/dubbing/index.ts"],"sourcesContent":["import type { SettingsSubmenuDef } from '../../controls/SettingsMenu';\nimport type { DubbingOptions, DubbingTrack } from '../../types';\nimport type { HopeLocaleStrings } from '../../i18n/types';\n\nexport interface DubbingPlayerContext {\n videoEl: HTMLVideoElement;\n loadSource(src: string, type?: string): Promise<void>;\n registerSubmenu(def: SettingsSubmenuDef): void;\n unregisterSubmenu(key: string): void;\n i18n: HopeLocaleStrings;\n}\n\nconst SUBMENU_KEY = 'dubbing';\n\nfunction dubLangCode(track: DubbingTrack): string {\n return (track.srclang || track.label || '').toUpperCase().slice(0, 3);\n}\n\n/** Ayarlar menüsüne \"Ses/Dil\" alt menüsü ekler (registerSubmenu). */\nexport class Dubbing {\n private activeIndex: number;\n\n constructor(\n private readonly ctx: DubbingPlayerContext,\n private readonly options: DubbingOptions\n ) {\n const defaultIdx = options.tracks.findIndex((t) => t.default);\n this.activeIndex = defaultIdx >= 0 ? defaultIdx : 0;\n\n this.registerMenu();\n }\n\n /** Dil sonradan değişince başlığı güncel `ctx.i18n.dubbingTitle`'la yeniden kaydeder — `registerSubmenu` aynı key'i replace eder. */\n refreshLabels(): void {\n this.registerMenu();\n }\n\n private registerMenu(): void {\n this.ctx.registerSubmenu({\n key: SUBMENU_KEY,\n title: this.ctx.i18n.dubbingTitle,\n getValueLabel: () => dubLangCode(this.options.tracks[this.activeIndex]!),\n getItems: () =>\n this.options.tracks.map((track, i) => ({\n label: track.label,\n active: i === this.activeIndex,\n onSelect: () => this.select(i),\n })),\n });\n }\n\n destroy(): void {\n this.ctx.unregisterSubmenu(SUBMENU_KEY);\n }\n\n private select(index: number): void {\n if (index === this.activeIndex) return;\n const track = this.options.tracks[index];\n if (!track) return;\n\n const resumeTime = this.ctx.videoEl.currentTime;\n const wasPlaying = !this.ctx.videoEl.paused;\n this.activeIndex = index;\n\n void this.ctx.loadSource(track.src, track.type).then(() => {\n this.ctx.videoEl.currentTime = resumeTime;\n if (wasPlaying) void this.ctx.videoEl.play().catch(() => {});\n });\n }\n}\n","import { Dubbing, type DubbingPlayerContext } from './Dubbing';\nimport type { DubbingOptions } from '../../types';\n\nexport function installDubbing(ctx: DubbingPlayerContext, options: DubbingOptions): Dubbing {\n return new Dubbing(ctx, options);\n}\n\nexport { Dubbing };\nexport type { DubbingPlayerContext };\n"],"names":["SUBMENU_KEY","dubLangCode","track","Dubbing","ctx","options","__publicField","defaultIdx","t","i","index","resumeTime","wasPlaying","installDubbing"],"mappings":";;;AAYA,MAAMA,IAAc;AAEpB,SAASC,EAAYC,GAA6B;AAC9C,UAAQA,EAAM,WAAWA,EAAM,SAAS,IAAI,cAAc,MAAM,GAAG,CAAC;AACxE;AAGO,MAAMC,EAAQ;AAAA,EAGjB,YACqBC,GACAC,GACnB;AALM,IAAAC,EAAA;AAGa,SAAA,MAAAF,GACA,KAAA,UAAAC;AAEjB,UAAME,IAAaF,EAAQ,OAAO,UAAU,CAACG,MAAMA,EAAE,OAAO;AAC5D,SAAK,cAAcD,KAAc,IAAIA,IAAa,GAElD,KAAK,aAAA;AAAA,EACT;AAAA;AAAA,EAGA,gBAAsB;AAClB,SAAK,aAAA;AAAA,EACT;AAAA,EAEQ,eAAqB;AACzB,SAAK,IAAI,gBAAgB;AAAA,MACrB,KAAKP;AAAA,MACL,OAAO,KAAK,IAAI,KAAK;AAAA,MACrB,eAAe,MAAMC,EAAY,KAAK,QAAQ,OAAO,KAAK,WAAW,CAAE;AAAA,MACvE,UAAU,MACN,KAAK,QAAQ,OAAO,IAAI,CAACC,GAAOO,OAAO;AAAA,QACnC,OAAOP,EAAM;AAAA,QACb,QAAQO,MAAM,KAAK;AAAA,QACnB,UAAU,MAAM,KAAK,OAAOA,CAAC;AAAA,MAAA,EAC/B;AAAA,IAAA,CACT;AAAA,EACL;AAAA,EAEA,UAAgB;AACZ,SAAK,IAAI,kBAAkBT,CAAW;AAAA,EAC1C;AAAA,EAEQ,OAAOU,GAAqB;AAChC,QAAIA,MAAU,KAAK,YAAa;AAChC,UAAMR,IAAQ,KAAK,QAAQ,OAAOQ,CAAK;AACvC,QAAI,CAACR,EAAO;AAEZ,UAAMS,IAAa,KAAK,IAAI,QAAQ,aAC9BC,IAAa,CAAC,KAAK,IAAI,QAAQ;AACrC,SAAK,cAAcF,GAEd,KAAK,IAAI,WAAWR,EAAM,KAAKA,EAAM,IAAI,EAAE,KAAK,MAAM;AACvD,WAAK,IAAI,QAAQ,cAAcS,GAC3BC,KAAiB,KAAK,IAAI,QAAQ,KAAA,EAAO,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAC/D,CAAC;AAAA,EACL;AACJ;AClEO,SAASC,EAAeT,GAA2BC,GAAkC;AACxF,SAAO,IAAIF,EAAQC,GAAKC,CAAO;AACnC;"}
@@ -136,4 +136,4 @@ export {
136
136
  g as GeoChecker,
137
137
  m as installGeoChecker
138
138
  };
139
- //# sourceMappingURL=index-BBmuCtKu.js.map
139
+ //# sourceMappingURL=geoChecker-BRtvHwI-.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geoChecker-BRtvHwI-.js","sources":["../../src/plugins/geo-checker/GeoChecker.ts","../../src/plugins/geo-checker/index.ts"],"sourcesContent":["import type { GeoCheckerOptions } from '../../types';\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\n\nconst EU_COUNTRIES = [\n 'EU', 'AD', 'AL', 'AT', 'BA', 'BE', 'BG', 'BY', 'CH', 'CS', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FO', 'FR', 'FX', 'GB', 'GI',\n 'GR', 'HR', 'HU', 'IE', 'IS', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MD', 'MK', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SI',\n 'SJ', 'SK', 'SM', 'UA', 'VA',\n];\nconst MENA_COUNTRIES = [\n 'DZ', 'BH', 'EG', 'IR', 'IQ', 'JO', 'KW', 'LB', 'LY', 'MA', 'OM', 'QA', 'SA', 'PS', 'SD', 'SY', 'TN', 'AE', 'YE',\n 'IL', 'DJ', 'TD', 'SO', 'MR', 'NL',\n];\n\n/** Ücretsiz, API anahtarı gerektirmeyen, CORS'a açık IP-coğrafya servisi. */\nconst DEFAULT_API_URL = 'https://get.geojs.io/v1/ip/geo.json';\n/** geojs'te ülke KODU (`\"TR\"`) — `country` alanı ülke ADI (`\"Türkiye\"`). */\nconst DEFAULT_PARAMETER = 'country_code';\n\n/**\n * IP-coğrafyasına göre erişim kontrolü. API'ye ulaşılamazsa erişime izin verir (fail-open) —\n * güvenlik değil, lisans/yayın bölgesi uyumluluğu.\n */\nexport class GeoChecker {\n private readonly loadingEl: HTMLElement;\n private destroyed = false;\n\n constructor(\n private readonly ctx: GatePlayerContext,\n private readonly options: GeoCheckerOptions\n ) {\n ctx.blockChrome();\n ctx.videoEl.addEventListener('play', this.onPlayWhileBlocked);\n\n this.loadingEl = document.createElement('div');\n this.loadingEl.setAttribute('part', 'geo-loading');\n this.loadingEl.className = 'hp:absolute hp:inset-0 hp:z-40 hp:flex hp:items-center hp:justify-center hp:bg-surface';\n this.loadingEl.innerHTML =\n '<div class=\"hp:w-8 hp:h-8 hp:rounded-full hp:border-2 hp:border-on-surface/30 hp:border-t-accent hp:animate-spin\"></div>';\n ctx.overlayContainerEl.appendChild(this.loadingEl);\n\n void this.check();\n }\n\n /** Uyarı ekranı bir kez (kalıcı olarak) render ediliyor — burada tazelenecek reaktif bir etiket yok, diğer gate plugin'leriyle TUTARLI bir çağrı yüzeyi için var. */\n refreshLabels(): void {\n /* no-op */\n }\n\n destroy(): void {\n this.destroyed = true;\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\n this.loadingEl.remove();\n }\n\n private readonly onPlayWhileBlocked = (): void => {\n this.ctx.videoEl.pause();\n };\n\n /** Varsayılan geojs: ülke kodu country_code'da (country alanı ülke adı). */\n private async resolveCountry(): Promise<string> {\n if (this.options.getCountry) return String((await this.options.getCountry()) ?? '');\n\n const response = await fetch(this.options.apiUrl || DEFAULT_API_URL);\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n const data: unknown = await response.json();\n const value = (this.options.parameter || DEFAULT_PARAMETER)\n .split('.')\n .reduce<unknown>((obj, key) => (obj && typeof obj === 'object' ? (obj as Record<string, unknown>)[key] : undefined), data);\n return typeof value === 'string' ? value : '';\n }\n\n private async check(): Promise<void> {\n let allowed = true;\n let userCountry = '';\n\n try {\n userCountry = (await this.resolveCountry()).trim().toUpperCase();\n\n let allowList = this.options.allowedCountries || [];\n if (this.options.region === 'EU') allowList = EU_COUNTRIES;\n else if (this.options.region === 'MENA') allowList = MENA_COUNTRIES;\n\n allowed = allowList.some((code) => code.trim().toUpperCase() === userCountry);\n } catch (err) {\n console.warn('[HopePlayer geo-checker] IP sorgusu başarısız, erişime izin veriliyor:', err);\n allowed = true;\n }\n\n if (this.destroyed) return;\n this.loadingEl.remove();\n\n if (allowed) {\n this.ctx.videoEl.removeEventListener('play', this.onPlayWhileBlocked);\n this.ctx.unblockChrome();\n return;\n }\n\n this.showWarning(userCountry);\n }\n\n private showWarning(country: string): void {\n const el = document.createElement('div');\n el.setAttribute('part', 'geo-warning');\n el.className = 'hp:absolute hp:inset-0 hp:z-40 hp:flex hp:flex-col hp:items-center hp:justify-center hp:gap-2 hp:bg-surface hp:text-on-surface hp:text-center hp:p-4';\n\n const messages = this.options.warningMessages?.length ? this.options.warningMessages : [this.ctx.i18n.geoDefaultWarning];\n for (const msg of messages) {\n const p = document.createElement('p');\n p.className = 'hp:text-sm hp:m-0';\n p.textContent = msg;\n el.appendChild(p);\n }\n\n const countryEl = document.createElement('span');\n countryEl.className = 'hp:text-xs hp:opacity-60';\n countryEl.textContent = country || this.ctx.i18n.geoUnknownCountry;\n el.appendChild(countryEl);\n\n this.ctx.overlayContainerEl.appendChild(el);\n // Erişim kalıcı olarak kapalı — unblockChrome() ÇAĞRILMIYOR.\n }\n}\n","import { GeoChecker } from './GeoChecker';\nimport type { GatePlayerContext } from '../shared/GatePlayerContext';\nimport type { GeoCheckerOptions } from '../../types';\n\nexport function installGeoChecker(ctx: GatePlayerContext, options: GeoCheckerOptions): GeoChecker {\n return new GeoChecker(ctx, options);\n}\n\nexport { GeoChecker };\nexport type { GatePlayerContext };\n"],"names":["EU_COUNTRIES","MENA_COUNTRIES","DEFAULT_API_URL","DEFAULT_PARAMETER","GeoChecker","ctx","options","__publicField","response","data","value","obj","key","allowed","userCountry","allowList","code","err","country","_a","el","messages","msg","p","countryEl","installGeoChecker"],"mappings":"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"}
@@ -65,4 +65,4 @@ export {
65
65
  h as GestureControls,
66
66
  d as installGesture
67
67
  };
68
- //# sourceMappingURL=index-Ca8hocby.js.map
68
+ //# sourceMappingURL=gesture-BzPCgi87.js.map