jaynesmax commited on
Commit
a797649
·
verified ·
1 Parent(s): 575ba1b

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +8 -316
index.html CHANGED
@@ -781,21 +781,6 @@
781
  #dlTopBtn .nav-badge{top:-8px;right:-10px}
782
  /* ── Player controls (Netflix/YouTube style) ── */
783
  .vwrap{position:relative;width:100%;aspect-ratio:16/9;max-height:100%;background:#000;-webkit-user-select:none;user-select:none}
784
- .jmx-ad{margin:14px 12px;position:relative}
785
- .jmx-ad-l{font-size:10px;letter-spacing:.6px;text-transform:uppercase;color:var(--muted,#8a8a8a);margin:0 0 4px 2px}
786
- .jmx-ad-b{width:100%;overflow:hidden;border-radius:10px;background:rgba(255,255,255,.04)}
787
- .jmx-ad-b iframe{border:0;display:block;transform-origin:0 0;background:transparent}
788
- .jmx-noad .jmx-sb{display:none!important}
789
- .jmx-pre-fixed{position:fixed!important;inset:0;z-index:100000!important}
790
- .jmx-pre{position:absolute;inset:0;z-index:9999;background:#000;display:flex;align-items:center;justify-content:center}
791
- .jmx-pre video{width:100%;height:100%;object-fit:contain;background:#000}
792
- .jmx-pre-top{position:absolute;left:0;right:0;top:0;display:flex;justify-content:space-between;align-items:center;padding:10px 12px;background:linear-gradient(rgba(0,0,0,.65),transparent);font-size:12px;color:#fff;pointer-events:none}
793
- .jmx-pre-btns{position:absolute;right:10px;bottom:14px;display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}
794
- .jmx-pre-btn{border:1px solid rgba(255,255,255,.4);background:rgba(0,0,0,.7);color:#fff;border-radius:999px;padding:8px 14px;font-size:13px;font-weight:700;cursor:pointer}
795
- .jmx-pre-btn[hidden]{display:none}
796
- .jmx-pre-btn:focus{outline:2px solid var(--accent2);outline-offset:2px}
797
- .jmx-pre-bar{position:absolute;left:0;right:0;bottom:0;height:3px;background:rgba(255,255,255,.2)}
798
- .jmx-pre-bar i{display:block;height:100%;width:0;background:var(--accent)}
799
  .vwrap video{width:100%;height:100%;max-height:none;aspect-ratio:auto;object-fit:contain}
800
  .vwrap:fullscreen,.vwrap:-webkit-full-screen{aspect-ratio:auto;max-height:none;height:100%}
801
  .vwrap .seek-zone{top:0;bottom:64px}
@@ -2072,7 +2057,7 @@ async function setKidsMode(on){
2072
  if (!ok) return false;
2073
  }
2074
  }
2075
- setSettings({ kidsMode: !!on }); try { jmxSyncAds(); } catch (_) {}
2076
  return true;
2077
  }
2078
  function kidsModeFilter(list){
@@ -2821,7 +2806,7 @@ const I18N_EXTRA7 = {"sw": {"not_live_msg": "Haipatikani kwa LIVE", "vol_warn":
2821
  Object.keys(I18N_EXTRA7).forEach(l => { I18N[l] = Object.assign(I18N[l] || {}, I18N_EXTRA7[l]); });
2822
  const I18N_EXTRA8 = {"sw": {"dq_paused_resume": "Imesimamishwa — gusa ↻ kuendelea"}, "en": {"dq_paused_resume": "Paused — tap ↻ to resume"}, "ar": {"dq_paused_resume": "متوقف مؤقتاً — اضغط ↻ للمتابعة"}, "fr": {"dq_paused_resume": "En pause — touchez ↻ pour reprendre"}};
2823
  Object.keys(I18N_EXTRA8).forEach(l => { I18N[l] = Object.assign(I18N[l] || {}, I18N_EXTRA8[l]); });
2824
- const I18N_EXTRA10 = {"sw": {"ad_label": "Tangazo", "ad_skip": "Ruka ›", "ad_skip_in": "Ruka baada ya {n}s", "ad_open": "Fungua tangazo ↗"}, "en": {"ad_label": "Ad", "ad_skip": "Skip ›", "ad_skip_in": "Skip in {n}s", "ad_open": "Open ad ↗"}, "ar": {"ad_label": "إعلان", "ad_skip": "تخطي ›", "ad_skip_in": "تخطي بعد {n} ث", "ad_open": "فتح الإعلان ↗"}, "fr": {"ad_label": "Publicité", "ad_skip": "Passer ›", "ad_skip_in": "Passer dans {n}s", "ad_open": "Ouvrir la pub ↗"}};
2825
  Object.keys(I18N_EXTRA10).forEach(l => { I18N[l] = Object.assign(I18N[l] || {}, I18N_EXTRA10[l]); });
2826
  function T(k, v) { return t(k, v); }
2827
  // Maandishi yaliyoandikwa kwenye HTML kupitia data-i18n / data-i18n-ph / data-i18n-title
@@ -3239,282 +3224,6 @@ function renderSkeletonRails(count = 3){
3239
  for (let i = 0; i < count; i++) railsEl.appendChild(skeletonRail());
3240
  }
3241
 
3242
- // ── Matangazo (Adsterra): banner + native kwenye Home ──
3243
- // Kila tangazo linaendeshwa ndani ya iframe iliyotengwa (sandbox, bila allow-same-origin) ili msimbo wa mtandao wa matangazo
3244
- // usiweze kusoma akaunti/token za app. Zima yote: JM_CONFIG.ADS_ENABLED = false kwenye config.js. Hali ya Mtoto haionyeshi matangazo.
3245
- const JMX_ADS = {
3246
- banner: { host: 'https://bancadeltempoidea.org', key: '2085a0d997c0512303b51c5bd2a70df3', w: 468, h: 60 },
3247
- social: { src: 'https://bancadeltempoidea.org/14/e742797728bf0e110ac81ff2ffe58ce0' },
3248
- native: { src: 'https://bancadeltempoidea.org/21/87f4e31e09a568f8e6c9f0e1f50c2b8d', id: 'container-87f4e31e09a568f8e6c9f0e1f50c2b8d', h: 300 },
3249
- };
3250
- function jmxAdsOn(){
3251
- try { if (window.JM_CONFIG && window.JM_CONFIG.ADS_ENABLED === false) return false; } catch (_) {}
3252
- return !isKidsMode() && navigator.onLine !== false;
3253
- }
3254
- function jmxAdSlot(kind){
3255
- if (!jmxAdsOn()) return null;
3256
- const c = JMX_ADS[kind]; if (!c) return null;
3257
- const wrap = document.createElement('div'); wrap.className = 'jmx-ad';
3258
- wrap.innerHTML = '<div class="jmx-ad-l">' + esc(T('ad_label')) + '</div><div class="jmx-ad-b"></div>';
3259
- const box = wrap.querySelector('.jmx-ad-b'), ifr = document.createElement('iframe');
3260
- ifr.setAttribute('sandbox', 'allow-scripts allow-popups allow-popups-to-escape-sandbox'); ifr.setAttribute('scrolling', 'no'); ifr.loading = 'lazy'; ifr.dataset.kind = kind;
3261
- const head = '<!doctype html><html><head><meta charset="utf-8"><base target="_blank"><style>html,body{margin:0;background:transparent;overflow:hidden}</style></head><body>';
3262
- // Baada ya sekunde 7 iframe inaripoti kama tangazo limepakia (ok) na urefu wake; kama tupu, nafasi inaondolewa
3263
- const probe = '<script>setTimeout(function(){try{var ok=!!document.body.querySelector("iframe,img,ins,a,video,canvas,div>*");parent.postMessage({jmxAd:1,ok:ok,h:document.documentElement.scrollHeight},"*")}catch(e){}},7000)<\/script>';
3264
- if (kind === 'banner') {
3265
- ifr.width = c.w; ifr.height = c.h;
3266
- ifr.srcdoc = head + '<script>atOptions = { "key": "' + c.key + '", "format": "iframe", "height": ' + c.h + ', "width": ' + c.w + ', "params": {} };<\/script><script src="' + c.host + '/22/' + c.key + '"><\/script>' + probe + '</body></html>';
3267
- const fit = () => { const k = Math.min(1, (box.clientWidth || (window.innerWidth - 24)) / c.w); ifr.style.transform = 'scale(' + k + ')'; box.style.height = Math.round(c.h * k) + 'px'; };
3268
- requestAnimationFrame(fit); window.addEventListener('resize', fit);
3269
- } else {
3270
- ifr.style.width = '100%'; ifr.height = c.h;
3271
- ifr.srcdoc = head + '<div id="' + c.id + '"></div><script async data-cfasync="false" src="' + c.src + '"><\/script>' + probe + '</body></html>';
3272
- }
3273
- box.appendChild(ifr);
3274
- return wrap;
3275
- }
3276
- window.addEventListener('message', e => {
3277
- const d = e.data; if (!d || d.jmxAd !== 1) return;
3278
- const ifr = [...document.querySelectorAll('.jmx-ad iframe')].find(f => f.contentWindow === e.source); if (!ifr) return;
3279
- if (!d.ok) ifr.closest('.jmx-ad').remove();
3280
- else if (ifr.dataset.kind === 'native' && d.h > 20) ifr.height = Math.min(d.h, 420);
3281
- });
3282
- // Social Bar: lazima iendeshwe kwenye ukurasa mkuu (haiwezi kutengwa kwenye iframe). Inafichwa player ikiwa wazi na Hali ya Mtoto ikiwa imewashwa.
3283
- let __jmxSb = false;
3284
- function jmxSyncAds(){ try { document.documentElement.classList.toggle('jmx-noad', isKidsMode() || playerEl.classList.contains('on')); } catch (_) {} }
3285
- function jmxSocialBar(){
3286
- if (__jmxSb || !jmxAdsOn() || !JMX_ADS.social) return;
3287
- __jmxSb = true;
3288
- const known = new Set(document.body.children);
3289
- new MutationObserver(ms => ms.forEach(m => m.addedNodes.forEach(n => {
3290
- if (n.nodeType === 1 && n.parentNode === document.body && !known.has(n)) { known.add(n); n.classList.add('jmx-sb'); }
3291
- }))).observe(document.body, { childList: true });
3292
- new MutationObserver(jmxSyncAds).observe(playerEl, { attributes: true, attributeFilter: ['class'] });
3293
- jmxSyncAds();
3294
- const sc = document.createElement('script'); sc.async = true; sc.setAttribute('data-cfasync', 'false'); sc.src = JMX_ADS.social.src; document.body.appendChild(sc);
3295
- }
3296
- // ── Video Ads (VAST) — HilltopAds ──
3297
- // Pre-roll: kila filamu/series/Live TV/mechi inapoanza (pamoja na kipindi kinachofuata).
3298
- // Mid-roll: kila dakika 10 za kutazama (kama YouTube). Download: tangazo kabla ya kuanza (juu 2 kwa download nyingi).
3299
- // HAZIONEKANI: offline (zilizopakuliwa), trailer, Hali ya Mtoto. Tangazo likishindikana kwa sababu yoyote, video inaendelea moja kwa moja.
3300
- // Zima kabisa: JM_CONFIG.ADS_ENABLED = false, au acha orodha ya JMX_VAST.urls tupu.
3301
- const JMX_VAST = {
3302
- // Kampuni za matangazo ya video (VAST). Ongeza kiungo kipya kwenye orodha hii. Zinabadilishana kila tangazo (round-robin);
3303
- // kampuni moja ikikosa tangazo (hakuna fill/hitilafu), inayofuata inajaribiwa mara moja.
3304
- urls: [
3305
- 'https://sadpicture.com/dMmlFsz.dhGcNovMZkGwUp/teFmT9hugZPUjl/kUPMT-c/1IM/TQAmxdN/j_kYt/NqzCUsxNM/DREX3AMdwv', // HilltopAds
3306
- // 'PAKA_VAST_URL_YA_KAMPUNI_YA_PILI_HAPA', // mf. ExoClick / RichAds
3307
- ],
3308
- fetchMs: 6000, // muda wa juu wa kupata VAST XML
3309
- startMs: 9000, // muda wa juu wa video ya tangazo kuanza kucheza
3310
- skipAfter: 5, // sekunde ya kuruhusu "Ruka" kama VAST haijaweka skipoffset
3311
- maxWrap: 4,
3312
- midrollEverySec: 10 * 60, // tangazo katikati ya video: kila sekunde hizi za kutazama
3313
- downloadAds: 2, // idadi ya juu ya matangazo kwa download moja au nyingi kwa pamoja
3314
- };
3315
- let __jmxPre = null; // tangazo linaloendelea sasa: { end(reason) }
3316
- let __jmxRR = 0; // round-robin: kampuni ipi inaanza tangazo linalofuata
3317
- function jmxVastUrls(){ return (JMX_VAST.urls || []).filter(u => u && /^https?:\/\//i.test(u)); }
3318
- // Hupata VAST kwa kuzunguka kampuni zote; ya kwanza yenye tangazo halisi inashinda.
3319
- async function jmxVastPick(){
3320
- const L = jmxVastUrls(); if (!L.length) throw new Error('no_urls');
3321
- const start = __jmxRR++ % L.length; let lastErr = null;
3322
- for (let k = 0; k < L.length; k++) {
3323
- try { return await jmxVastLoad(L[(start + k) % L.length], 0, { imps: [], errs: [], clickTr: [], track: {}, media: '', click: '', dur: null, skipoff: '' }); }
3324
- catch (e) { lastErr = e; }
3325
- }
3326
- throw lastErr || new Error('no_fill');
3327
- }
3328
- let __jmxPrePromise = null; // tangazo la kuanza-kucheza linalosubiriwa na player
3329
- function jmxPrerollAbort(){ try { if (__jmxPre) __jmxPre.end('aborted'); } catch (_) {} }
3330
- // Player huita hii kabla ya kuanza kucheza: inasubiri tangazo likiisha. false = mtumiaji alibadilisha/alifunga.
3331
- async function jmxGate(){
3332
- const p = __jmxPrePromise; if (!p) return true;
3333
- return (await p) !== 'aborted';
3334
- }
3335
- function jmxStartForPlayer(){
3336
- const p = jmxPreroll({});
3337
- __jmxPrePromise = p;
3338
- p.then(() => { if (__jmxPrePromise === p) __jmxPrePromise = null; });
3339
- }
3340
- function jmxVastSecs(s){
3341
- s = (s || '').trim();
3342
- const m = /^(\d+):(\d+):(\d+(?:\.\d+)?)$/.exec(s);
3343
- return m ? (+m[1]) * 3600 + (+m[2]) * 60 + parseFloat(m[3]) : null;
3344
- }
3345
- function jmxPing(u, code){
3346
- if (!u) return;
3347
- try {
3348
- u = u.replace(/\[(CACHEBUSTING|TIMESTAMP|RANDOM)\]/g, () => String(Date.now()) + Math.floor(Math.random() * 1e6)).replace(/\[ERRORCODE\]/g, String(code || 900));
3349
- const i = new Image(); i.referrerPolicy = 'no-referrer-when-downgrade'; i.src = u;
3350
- } catch (_) {}
3351
- }
3352
- async function jmxVastLoad(url, depth, acc){
3353
- const ctl = new AbortController(), to = setTimeout(() => ctl.abort(), JMX_VAST.fetchMs);
3354
- let txt;
3355
- try {
3356
- const r = await fetch(url, { signal: ctl.signal, credentials: 'omit' });
3357
- if (!r.ok) throw new Error('http ' + r.status);
3358
- txt = await r.text();
3359
- } finally { clearTimeout(to); }
3360
- const doc = new DOMParser().parseFromString(txt, 'text/xml');
3361
- if (doc.getElementsByTagName('parsererror').length) throw new Error('xml');
3362
- const ad = doc.getElementsByTagName('Ad')[0];
3363
- if (!ad) throw new Error('empty');
3364
- const tx = el => ((el && el.textContent) || '').trim();
3365
- const all = tag => Array.from(ad.getElementsByTagName(tag));
3366
- all('Impression').forEach(e => { const u = tx(e); if (u) acc.imps.push(u); });
3367
- all('Error').forEach(e => { const u = tx(e); if (u) acc.errs.push(u); });
3368
- all('ClickTracking').forEach(e => { const u = tx(e); if (u) acc.clickTr.push(u); });
3369
- all('Tracking').forEach(e => { const ev = e.getAttribute('event'), u = tx(e); if (ev && u) (acc.track[ev] = acc.track[ev] || []).push(u); });
3370
- if (ad.getElementsByTagName('Wrapper')[0]) {
3371
- const next = tx(ad.getElementsByTagName('VASTAdTagURI')[0]);
3372
- if (!next || depth >= JMX_VAST.maxWrap) throw new Error('wrapper');
3373
- return jmxVastLoad(next, depth + 1, acc);
3374
- }
3375
- const lin = all('Linear')[0];
3376
- if (!lin) throw new Error('no_linear');
3377
- const files = all('MediaFile').map(e => ({
3378
- url: tx(e), type: (e.getAttribute('type') || '').toLowerCase(), w: +e.getAttribute('width') || 0,
3379
- prog: !/streaming/i.test(e.getAttribute('delivery') || 'progressive'),
3380
- })).filter(f => f.url && /video\/(mp4|webm)/.test(f.type) && f.prog);
3381
- if (!files.length) throw new Error('no_media');
3382
- const can = f => { try { return !!document.createElement('video').canPlayType(f.type); } catch (_) { return true; } };
3383
- const ok = files.filter(can); const pool = ok.length ? ok : files;
3384
- pool.sort((a, b) => Math.abs((a.w || 640) - 720) - Math.abs((b.w || 640) - 720));
3385
- acc.media = pool[0].url;
3386
- acc.click = tx(all('ClickThrough')[0]) || '';
3387
- acc.dur = jmxVastSecs(tx(all('Duration')[0]));
3388
- acc.skipoff = lin.getAttribute('skipoffset') || '';
3389
- return acc;
3390
- }
3391
- // opts: { fixed: skrini nzima juu ya app (download), mid: katikati ya video, onReady: ikaitwa tangazo linapokuwa tayari kuonyeshwa }
3392
- function jmxPreroll(opts){
3393
- opts = opts || {};
3394
- if (!jmxVastUrls().length || !jmxAdsOn()) return Promise.resolve('skipped');
3395
- if (!opts.fixed && playerEl.classList.contains('mini')) return Promise.resolve('skipped');
3396
- jmxPrerollAbort();
3397
- return new Promise(resolve => {
3398
- let ov = null, av = null, host = null, vast = null, done = false, fired = {}, timers = [], mo = null, hostPos = null;
3399
- const track = (ev) => { if (vast && vast.track[ev]) vast.track[ev].forEach(u => jmxPing(u)); };
3400
- const once = (ev) => { if (fired[ev]) return; fired[ev] = 1; track(ev); };
3401
- const end = (reason) => {
3402
- if (done) return; done = true;
3403
- timers.forEach(clearTimeout); timers.forEach(clearInterval);
3404
- try { if (mo) mo.disconnect(); } catch (_) {}
3405
- try { if (av) { av.pause(); av.removeAttribute('src'); av.load(); } } catch (_) {}
3406
- try { if (ov && ov.parentNode) ov.parentNode.removeChild(ov); } catch (_) {}
3407
- try { if (host && hostPos != null) host.style.position = hostPos; } catch (_) {}
3408
- if (__jmxPre && __jmxPre.end === end) __jmxPre = null;
3409
- resolve(reason);
3410
- };
3411
- __jmxPre = { end };
3412
- (async () => {
3413
- try {
3414
- vast = await jmxVastPick();
3415
- } catch (e) { return end('failed'); }
3416
- if (done) return;
3417
- if (opts.fixed) host = document.body;
3418
- else {
3419
- if (!playerEl.classList.contains('on')) return end('failed');
3420
- host = document.fullscreenElement || stage;
3421
- if (host && host.tagName === 'VIDEO') { try { document.exitFullscreen(); } catch (_) {} host = stage; }
3422
- if (!host) return end('failed');
3423
- if (getComputedStyle(host).position === 'static') { hostPos = host.style.position; host.style.position = 'relative'; }
3424
- }
3425
- try { if (opts.onReady) opts.onReady(); } catch (_) {}
3426
- ov = document.createElement('div'); ov.className = 'jmx-pre' + (opts.fixed ? ' jmx-pre-fixed' : '');
3427
- ov.innerHTML = '<video playsinline webkit-playsinline preload="auto"></video>' +
3428
- '<div class="jmx-pre-top"><span>' + esc(T('ad_label')) + '</span><span class="jmx-pre-t"></span></div>' +
3429
- '<div class="jmx-pre-btns"><button type="button" class="jmx-pre-btn jmx-pre-mute" hidden>🔇</button>' +
3430
- '<button type="button" class="jmx-pre-btn jmx-pre-open" hidden>' + esc(T('ad_open')) + '</button>' +
3431
- '<button type="button" class="jmx-pre-btn jmx-pre-skip" hidden></button></div>' +
3432
- '<div class="jmx-pre-bar"><i></i></div>';
3433
- host.appendChild(ov);
3434
- av = ov.querySelector('video');
3435
- const tEl = ov.querySelector('.jmx-pre-t'), skipB = ov.querySelector('.jmx-pre-skip'), openB = ov.querySelector('.jmx-pre-open'),
3436
- muteB = ov.querySelector('.jmx-pre-mute'), bar = ov.querySelector('.jmx-pre-bar i');
3437
- // Kulinda: mtumiaji akifunga player, au kitu kikifuta tangazo, tangazo linaisha
3438
- if (!opts.fixed) {
3439
- mo = new MutationObserver(() => { if (!playerEl.classList.contains('on') || !ov.isConnected) end(ov.isConnected ? 'aborted' : 'done'); });
3440
- mo.observe(playerEl, { attributes: true, attributeFilter: ['class'] });
3441
- }
3442
- timers.push(setTimeout(() => { if (!fired.__playing) { vast.errs.forEach(u => jmxPing(u, 402)); end('failed'); } }, JMX_VAST.startMs));
3443
- av.addEventListener('error', () => { vast.errs.forEach(u => jmxPing(u, 405)); end('failed'); });
3444
- av.addEventListener('playing', () => {
3445
- if (fired.__playing) return; fired.__playing = 1;
3446
- vast.imps.forEach(u => jmxPing(u)); once('creativeView'); once('start');
3447
- if (vast.click) openB.hidden = false;
3448
- });
3449
- av.addEventListener('pause', () => { if (!av.ended && fired.__playing) track('pause'); });
3450
- av.addEventListener('play', () => { if (fired.__playing) track('resume'); });
3451
- av.addEventListener('ended', () => { once('complete'); end('done'); });
3452
- muteB.onclick = () => { av.muted = !av.muted; muteB.textContent = av.muted ? '🔇' : '🔊'; track(av.muted ? 'mute' : 'unmute'); };
3453
- openB.onclick = () => {
3454
- vast.clickTr.forEach(u => jmxPing(u));
3455
- try { window.open(vast.click, '_blank', 'noopener'); } catch (_) {}
3456
- try { av.pause(); } catch (_) {}
3457
- };
3458
- skipB.onclick = () => { if (skipB.disabled) return; track('skip'); end('done'); };
3459
- const tick = () => {
3460
- if (!ov.isConnected) return end('done');
3461
- const d = isFinite(av.duration) && av.duration > 0 ? av.duration : (vast.dur || 0), c = av.currentTime || 0;
3462
- if (d) {
3463
- bar.style.width = Math.min(100, c / d * 100) + '%';
3464
- const left = Math.max(0, Math.ceil(d - c)); tEl.textContent = Math.floor(left / 60) + ':' + String(left % 60).padStart(2, '0');
3465
- if (c >= d * .25) once('firstQuartile'); if (c >= d * .5) once('midpoint'); if (c >= d * .75) once('thirdQuartile');
3466
- }
3467
- let so = jmxVastSecs(vast.skipoff);
3468
- if (so == null && /%$/.test(vast.skipoff) && d) so = d * parseFloat(vast.skipoff) / 100;
3469
- if (so == null) so = JMX_VAST.skipAfter;
3470
- if (d && so >= d) so = Math.max(0, d - 1);
3471
- skipB.hidden = false;
3472
- if (c >= so) { skipB.disabled = false; skipB.textContent = T('ad_skip'); }
3473
- else { skipB.disabled = true; skipB.textContent = T('ad_skip_in', { n: Math.ceil(so - c) }); }
3474
- };
3475
- timers.push(setInterval(tick, 250));
3476
- av.src = vast.media;
3477
- av.muted = false;
3478
- const pr = av.play();
3479
- if (pr && pr.catch) pr.catch(() => { av.muted = true; muteB.hidden = false; muteB.textContent = '🔇'; av.play().catch(() => { vast.errs.forEach(u => jmxPing(u, 400)); end('failed'); }); });
3480
- setTimeout(() => { if (!done) { muteB.hidden = false; muteB.textContent = av.muted ? '🔇' : '🔊'; } }, 800);
3481
- })();
3482
- });
3483
- }
3484
- // Tangazo katikati ya video (kama YouTube): kila JMX_VAST.midrollEverySec za kutazama kweli (si wakati imesimama).
3485
- function jmxMidroll(v){
3486
- if (!jmxVastUrls().length || !v || v.__jmxMid) return;
3487
- v.__jmxMid = 1;
3488
- let acc = 0, busy = false, adOn = false;
3489
- v.addEventListener('play', () => { if (adOn) { try { v.pause(); } catch (_) {} } });
3490
- const iv = setInterval(async () => {
3491
- if (!v.isConnected) return clearInterval(iv);
3492
- if (busy || v.paused || v.ended || v.seeking || v.readyState < 3 || document.hidden) return;
3493
- if (!jmxAdsOn() || playerEl.classList.contains('mini')) return;
3494
- if (++acc < JMX_VAST.midrollEverySec) return;
3495
- acc = 0; busy = true;
3496
- let r = 'failed';
3497
- try { r = await jmxPreroll({ mid: true, onReady: () => { adOn = true; try { v.pause(); } catch (_) {} } }); } catch (_) {}
3498
- adOn = false; busy = false;
3499
- if (!v.isConnected || r === 'aborted') return;
3500
- try { // Live: rudi kwenye wakati wa sasa, si mahali ulipoacha
3501
- if (!isFinite(v.duration)) {
3502
- if (hls && hls.liveSyncPosition) v.currentTime = hls.liveSyncPosition;
3503
- else if (shakaPlayer && shakaPlayer.isLive && shakaPlayer.isLive()) v.currentTime = shakaPlayer.seekRange().end;
3504
- }
3505
- } catch (_) {}
3506
- if (v.paused) v.play().catch(() => {});
3507
- }, 1000);
3508
- }
3509
- // Download: tangazo 1 kwa download moja; kwa nyingi kwa pamoja (mf. 5) matangazo yasizidi JMX_VAST.downloadAds (2).
3510
- async function jmxDownloadAds(n){
3511
- if (!jmxVastUrls().length || !jmxAdsOn()) return;
3512
- const times = Math.max(1, Math.min(JMX_VAST.downloadAds, n || 1));
3513
- for (let i = 0; i < times; i++) {
3514
- const r = await jmxPreroll({ fixed: true });
3515
- if (r !== 'done') break;
3516
- }
3517
- }
3518
  function renderRails(sections, gridMode = false) {
3519
  railsEl.innerHTML = '';
3520
  if (isKidsMode()) sections = sections.map(sec => ({ ...sec, items: kidsModeFilter(sec.items) })).filter(sec => sec.items.length);
@@ -3523,7 +3232,7 @@ function renderRails(sections, gridMode = false) {
3523
  fadeInScreen(railsEl);
3524
  return;
3525
  }
3526
- sections.forEach((sec, si) => {
3527
  const wrap = document.createElement('div');
3528
  wrap.className = 'rail';
3529
  const scroll = document.createElement('div');
@@ -3532,9 +3241,7 @@ function renderRails(sections, gridMode = false) {
3532
  wrap.innerHTML = `<div class="rail-title">${esc(sec.title)}</div>`;
3533
  wrap.appendChild(scroll);
3534
  railsEl.appendChild(wrap);
3535
- if (!gridMode && (si === 1 || si === 4)) { const ad = jmxAdSlot(si === 1 ? 'banner' : 'native'); if (ad) railsEl.appendChild(ad); } // banner baada ya rail ya 2, native baada ya ya 5
3536
  });
3537
- if (!gridMode) setTimeout(jmxSocialBar, 4000);
3538
  fadeInScreen(railsEl);
3539
  }
3540
 
@@ -4068,7 +3775,6 @@ function renderTranslatedDetail(d) {
4068
  if (d.isSeries || d.isParts) { openTranslatedDownloadSheet(d); return; }
4069
  const url = urlOf(null, null);
4070
  if (!url) { showToast(t('tr_no_dl')); return; }
4071
- try { await jmxDownloadAds(1); } catch (_) {}
4072
  queueTranslatedDownload(d, url, '');
4073
  };
4074
  document.getElementById('trShareBtn').onclick = () => shareTranslatedTitle(d);
@@ -4109,13 +3815,12 @@ function playTranslatedUrl(url, title, playlist, meta) {
4109
  stage.innerHTML = '<video id="vid" controls autoplay playsinline></video>';
4110
  const v = document.getElementById('vid');
4111
  attachPlayerEnhancements(v);
4112
- jmxMidroll(v);
4113
  renderSpeedChips(v); // speed (gear ⚙) sasa ipo kwenye zilizotafsiriwa pia
4114
  if (playlist) setPlayerPlaylist(playlist); // kichupo cha pembeni: vipindi / sehemu
4115
  ensureSound(v);
4116
  v.addEventListener('ended', () => { const c = window.__pcPlaylist; if (c && typeof c.next === 'function') c.next(); });
4117
  // Tangazo la video kwanza (likishindikana/likiruka, filamu inaanza mara moja)
4118
- jmxGate().then(ok => { if (ok && v.isConnected) v.src = url; });
4119
  // Route ya player: #/translated/ID/play?se=..&ep=..
4120
  try {
4121
  const id = currentTranslatedDetail && currentTranslatedDetail.id;
@@ -6242,7 +5947,6 @@ function stopMediaOnly(){
6242
  currentBlobUrls = [];
6243
  }
6244
  function stopPlayer(){
6245
- jmxPrerollAbort();
6246
  playerEl.classList.remove('mini');
6247
  clearUpNext();
6248
  if (document.pictureInPictureElement) { document.exitPictureInPicture().catch(()=>{}); }
@@ -6259,15 +5963,12 @@ function stopPlayer(){
6259
  currentResumeMeta = null;
6260
  const pipBtn = document.getElementById('pipBtn'); if (pipBtn) pipBtn.style.display = 'none';
6261
  }
6262
- function openPlayerShell(title, opts){
6263
  liveFb = null;
6264
- jmxPrerollAbort();
6265
- __jmxPrePromise = null;
6266
  stopPlayer();
6267
  ptitle.textContent = title;
6268
  playerEl.classList.add('on');
6269
  statusMsg(T('stream_searching'));
6270
- if (!(opts && opts.noAd)) jmxStartForPlayer(); // tangazo la kuanza kila player ya mtandaoni (offline/trailer: noAd)
6271
  }
6272
 
6273
  // ════════════════════════════════════════════════════════════════
@@ -6334,12 +6035,10 @@ function collectUrls(o, out = []) {
6334
  }
6335
 
6336
  async function playHlsUrl(url, opts = {}) {
6337
- if (!(await jmxGate())) return; // subiri tangazo la kuanza likiisha
6338
  const same = !!(opts.authHeader && opts.sameOriginBase && url.startsWith(opts.sameOriginBase));
6339
  stage.innerHTML = '<video id="vid" controls autoplay playsinline></video>';
6340
  const v = document.getElementById('vid');
6341
  attachPlayerEnhancements(v);
6342
- jmxMidroll(v);
6343
  ensureSound(v);
6344
  if (window.Hls && Hls.isSupported()) {
6345
  hls = new Hls({ xhrSetup: xhr => { if (same) xhr.setRequestHeader('Authorization', opts.authHeader); } });
@@ -6387,7 +6086,7 @@ async function openFawaMatch(item) {
6387
  const urls = collectUrls(data);
6388
  const media = urls.find(u => /\.m3u8|\.mp4/i.test(u));
6389
  if (media) return playHlsUrl(media, {});
6390
- if (urls[0]) { if (!(await jmxGate())) return; stage.innerHTML = '<iframe allowfullscreen allow="autoplay; fullscreen" src="' + esc(urls[0]) + '"></iframe>'; return; }
6391
  stage.innerHTML = '<pre>' + esc(JSON.stringify(data, null, 2)) + '</pre>';
6392
  return;
6393
  }
@@ -6775,7 +6474,6 @@ function attachContinueWatchingTracking(v){
6775
  }
6776
 
6777
  async function loadIntoVideo(pr, quality){
6778
- if (!(await jmxGate())) return; // subiri tangazo la kuanza likiisha
6779
  const url = (quality && (quality.proxyStreamUrl || quality.streamUrl)) || pr.playUrl;
6780
  const type = (pr.streamType || '').toUpperCase();
6781
  const gen = ++playGen;
@@ -6793,7 +6491,6 @@ async function loadIntoVideo(pr, quality){
6793
  wireUpNext(v);
6794
  wireSkipButtons(v);
6795
  renderSpeedChips(v);
6796
- jmxMidroll(v);
6797
 
6798
  if (type === 'DASH' && window.shaka && pr.clearKey && !window.isSecureContext) {
6799
  pcError(T('err_drm'), false);
@@ -6863,7 +6560,6 @@ async function playResultInPlayer(pr, title, resumeMeta){
6863
  currentResumeMeta = resumeMeta || null;
6864
  if (!pr) { statusMsg(T('err_no_stream')); return; }
6865
  if (!pr.playUrl && pr.iframeUrl) {
6866
- if (!(await jmxGate())) return;
6867
  stage.innerHTML = '<iframe allowfullscreen allow="autoplay; fullscreen" src="' + esc(pr.iframeUrl) + '"></iframe>';
6868
  return;
6869
  }
@@ -7068,7 +6764,7 @@ function formatTrailerDuration(sec){
7068
  // Hufungua trailer kwenye player ya kawaida ya app (fullscreen, na udhibiti wa kisasa),
7069
  // badala ya video ya <video controls> ndani ya ukurasa — sawa na uzoefu wa filamu/vipindi.
7070
  function playTrailerUrl(url, title){
7071
- openPlayerShell(title || 'Trailer', { noAd: true });
7072
  stage.innerHTML = '<video id="vid" src="' + esc(url) + '" controls autoplay playsinline></video>';
7073
  const v = document.getElementById('vid');
7074
  attachPlayerEnhancements(v);
@@ -7612,7 +7308,6 @@ function wireShortsSlideEvents(el) {
7612
  async function shortsDownloadCurrent(idx) {
7613
  const item = shortsQueue[idx];
7614
  if (!item || !item.url) { toastMsg(t('dl_short_loading')); setTimeout(() => (toastEl.textContent = ''), 2000); return; }
7615
- try { await jmxDownloadAds(1); } catch (_) {}
7616
  try {
7617
  const subs = (item.pr && item.pr.subtitles || []).filter(s => s && s.url).map(s => ({ url: s.url, language: s.language, label: s.label }));
7618
  const fname = `${shortsMeta.title || item.title} EP${padEp(item.ep)}.mp4`;
@@ -8905,7 +8600,7 @@ async function scanEmbeddedSubs(v, file, id){
8905
  // subs: [{label, language, vtt}] — opts: { id, pick, delay } (id = movie ya maktaba ya offline)
8906
  function playLocalVideo(url, title, subs, opts){
8907
  opts = opts || {};
8908
- openPlayerShell(title, { noAd: true }); // offline: hakuna tangazo
8909
  offCurId = opts.id || null;
8910
  offSubDelay = Number(opts.delay) || 0;
8911
  if (offSubScale !== 1) applySubScale();
@@ -9879,9 +9574,6 @@ async function muxJob(videoUrl, subtitles, filename, onProgress){
9879
  async function realDlConfirmHandler() {
9880
  const items = dlItemsCache.filter(it => dlSelection.has(it.key));
9881
  if (!items.length) return;
9882
- if (window.__dlAdBusy) return;
9883
- window.__dlAdBusy = true;
9884
- try { await jmxDownloadAds(items.length); } catch (_) {} finally { window.__dlAdBusy = false; } // tangazo kabla ya download (juu 2 kwa nyingi)
9885
 
9886
  // Washa ruhusa ya arifa (kama mtumiaji ameiwasha kwenye Mipangilio na bado hajajibu)
9887
  if (getSettings().downloadNotifications && typeof Notification !== 'undefined' && Notification.permission === 'default') {
 
781
  #dlTopBtn .nav-badge{top:-8px;right:-10px}
782
  /* ── Player controls (Netflix/YouTube style) ── */
783
  .vwrap{position:relative;width:100%;aspect-ratio:16/9;max-height:100%;background:#000;-webkit-user-select:none;user-select:none}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
784
  .vwrap video{width:100%;height:100%;max-height:none;aspect-ratio:auto;object-fit:contain}
785
  .vwrap:fullscreen,.vwrap:-webkit-full-screen{aspect-ratio:auto;max-height:none;height:100%}
786
  .vwrap .seek-zone{top:0;bottom:64px}
 
2057
  if (!ok) return false;
2058
  }
2059
  }
2060
+ setSettings({ kidsMode: !!on });
2061
  return true;
2062
  }
2063
  function kidsModeFilter(list){
 
2806
  Object.keys(I18N_EXTRA7).forEach(l => { I18N[l] = Object.assign(I18N[l] || {}, I18N_EXTRA7[l]); });
2807
  const I18N_EXTRA8 = {"sw": {"dq_paused_resume": "Imesimamishwa — gusa ↻ kuendelea"}, "en": {"dq_paused_resume": "Paused — tap ↻ to resume"}, "ar": {"dq_paused_resume": "متوقف مؤقتاً — اضغط ↻ للمتابعة"}, "fr": {"dq_paused_resume": "En pause — touchez ↻ pour reprendre"}};
2808
  Object.keys(I18N_EXTRA8).forEach(l => { I18N[l] = Object.assign(I18N[l] || {}, I18N_EXTRA8[l]); });
2809
+ const I18N_EXTRA10 = {"sw": {}, "en": {}, "ar": {}, "fr": {}};
2810
  Object.keys(I18N_EXTRA10).forEach(l => { I18N[l] = Object.assign(I18N[l] || {}, I18N_EXTRA10[l]); });
2811
  function T(k, v) { return t(k, v); }
2812
  // Maandishi yaliyoandikwa kwenye HTML kupitia data-i18n / data-i18n-ph / data-i18n-title
 
3224
  for (let i = 0; i < count; i++) railsEl.appendChild(skeletonRail());
3225
  }
3226
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3227
  function renderRails(sections, gridMode = false) {
3228
  railsEl.innerHTML = '';
3229
  if (isKidsMode()) sections = sections.map(sec => ({ ...sec, items: kidsModeFilter(sec.items) })).filter(sec => sec.items.length);
 
3232
  fadeInScreen(railsEl);
3233
  return;
3234
  }
3235
+ sections.forEach((sec) => {
3236
  const wrap = document.createElement('div');
3237
  wrap.className = 'rail';
3238
  const scroll = document.createElement('div');
 
3241
  wrap.innerHTML = `<div class="rail-title">${esc(sec.title)}</div>`;
3242
  wrap.appendChild(scroll);
3243
  railsEl.appendChild(wrap);
 
3244
  });
 
3245
  fadeInScreen(railsEl);
3246
  }
3247
 
 
3775
  if (d.isSeries || d.isParts) { openTranslatedDownloadSheet(d); return; }
3776
  const url = urlOf(null, null);
3777
  if (!url) { showToast(t('tr_no_dl')); return; }
 
3778
  queueTranslatedDownload(d, url, '');
3779
  };
3780
  document.getElementById('trShareBtn').onclick = () => shareTranslatedTitle(d);
 
3815
  stage.innerHTML = '<video id="vid" controls autoplay playsinline></video>';
3816
  const v = document.getElementById('vid');
3817
  attachPlayerEnhancements(v);
 
3818
  renderSpeedChips(v); // speed (gear ⚙) sasa ipo kwenye zilizotafsiriwa pia
3819
  if (playlist) setPlayerPlaylist(playlist); // kichupo cha pembeni: vipindi / sehemu
3820
  ensureSound(v);
3821
  v.addEventListener('ended', () => { const c = window.__pcPlaylist; if (c && typeof c.next === 'function') c.next(); });
3822
  // Tangazo la video kwanza (likishindikana/likiruka, filamu inaanza mara moja)
3823
+ v.src = url;
3824
  // Route ya player: #/translated/ID/play?se=..&ep=..
3825
  try {
3826
  const id = currentTranslatedDetail && currentTranslatedDetail.id;
 
5947
  currentBlobUrls = [];
5948
  }
5949
  function stopPlayer(){
 
5950
  playerEl.classList.remove('mini');
5951
  clearUpNext();
5952
  if (document.pictureInPictureElement) { document.exitPictureInPicture().catch(()=>{}); }
 
5963
  currentResumeMeta = null;
5964
  const pipBtn = document.getElementById('pipBtn'); if (pipBtn) pipBtn.style.display = 'none';
5965
  }
5966
+ function openPlayerShell(title){
5967
  liveFb = null;
 
 
5968
  stopPlayer();
5969
  ptitle.textContent = title;
5970
  playerEl.classList.add('on');
5971
  statusMsg(T('stream_searching'));
 
5972
  }
5973
 
5974
  // ════════════════════════════════════════════════════════════════
 
6035
  }
6036
 
6037
  async function playHlsUrl(url, opts = {}) {
 
6038
  const same = !!(opts.authHeader && opts.sameOriginBase && url.startsWith(opts.sameOriginBase));
6039
  stage.innerHTML = '<video id="vid" controls autoplay playsinline></video>';
6040
  const v = document.getElementById('vid');
6041
  attachPlayerEnhancements(v);
 
6042
  ensureSound(v);
6043
  if (window.Hls && Hls.isSupported()) {
6044
  hls = new Hls({ xhrSetup: xhr => { if (same) xhr.setRequestHeader('Authorization', opts.authHeader); } });
 
6086
  const urls = collectUrls(data);
6087
  const media = urls.find(u => /\.m3u8|\.mp4/i.test(u));
6088
  if (media) return playHlsUrl(media, {});
6089
+ if (urls[0]) { stage.innerHTML = '<iframe allowfullscreen allow="autoplay; fullscreen" src="' + esc(urls[0]) + '"></iframe>'; return; }
6090
  stage.innerHTML = '<pre>' + esc(JSON.stringify(data, null, 2)) + '</pre>';
6091
  return;
6092
  }
 
6474
  }
6475
 
6476
  async function loadIntoVideo(pr, quality){
 
6477
  const url = (quality && (quality.proxyStreamUrl || quality.streamUrl)) || pr.playUrl;
6478
  const type = (pr.streamType || '').toUpperCase();
6479
  const gen = ++playGen;
 
6491
  wireUpNext(v);
6492
  wireSkipButtons(v);
6493
  renderSpeedChips(v);
 
6494
 
6495
  if (type === 'DASH' && window.shaka && pr.clearKey && !window.isSecureContext) {
6496
  pcError(T('err_drm'), false);
 
6560
  currentResumeMeta = resumeMeta || null;
6561
  if (!pr) { statusMsg(T('err_no_stream')); return; }
6562
  if (!pr.playUrl && pr.iframeUrl) {
 
6563
  stage.innerHTML = '<iframe allowfullscreen allow="autoplay; fullscreen" src="' + esc(pr.iframeUrl) + '"></iframe>';
6564
  return;
6565
  }
 
6764
  // Hufungua trailer kwenye player ya kawaida ya app (fullscreen, na udhibiti wa kisasa),
6765
  // badala ya video ya <video controls> ndani ya ukurasa — sawa na uzoefu wa filamu/vipindi.
6766
  function playTrailerUrl(url, title){
6767
+ openPlayerShell(title || 'Trailer');
6768
  stage.innerHTML = '<video id="vid" src="' + esc(url) + '" controls autoplay playsinline></video>';
6769
  const v = document.getElementById('vid');
6770
  attachPlayerEnhancements(v);
 
7308
  async function shortsDownloadCurrent(idx) {
7309
  const item = shortsQueue[idx];
7310
  if (!item || !item.url) { toastMsg(t('dl_short_loading')); setTimeout(() => (toastEl.textContent = ''), 2000); return; }
 
7311
  try {
7312
  const subs = (item.pr && item.pr.subtitles || []).filter(s => s && s.url).map(s => ({ url: s.url, language: s.language, label: s.label }));
7313
  const fname = `${shortsMeta.title || item.title} EP${padEp(item.ep)}.mp4`;
 
8600
  // subs: [{label, language, vtt}] — opts: { id, pick, delay } (id = movie ya maktaba ya offline)
8601
  function playLocalVideo(url, title, subs, opts){
8602
  opts = opts || {};
8603
+ openPlayerShell(title);
8604
  offCurId = opts.id || null;
8605
  offSubDelay = Number(opts.delay) || 0;
8606
  if (offSubScale !== 1) applySubScale();
 
9574
  async function realDlConfirmHandler() {
9575
  const items = dlItemsCache.filter(it => dlSelection.has(it.key));
9576
  if (!items.length) return;
 
 
 
9577
 
9578
  // Washa ruhusa ya arifa (kama mtumiaji ameiwasha kwenye Mipangilio na bado hajajibu)
9579
  if (getSettings().downloadNotifications && typeof Notification !== 'undefined' && Notification.permission === 'default') {