Spaces:
Running
Running
Upload index.html
Browse files- index.html +99 -44
index.html
CHANGED
|
@@ -1226,6 +1226,13 @@
|
|
| 1226 |
/* Nafasi ya kusogeza (scroll) ili kipengele chenye focus kisifichwe na topbar / nav */
|
| 1227 |
.poster,.cw-card,.tab-chip,.settings-row,.dq-item,.tr-ep,.cast-item{scroll-margin:110px 3vw 110px 3vw;}
|
| 1228 |
</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1229 |
</head>
|
| 1230 |
<body>
|
| 1231 |
<div id="gate">
|
|
@@ -1496,34 +1503,24 @@ const PIXTVMAX_KEY = SUPABASE_ANON_KEY;
|
|
| 1496 |
const TRAILER_BASE = JM_CONFIG.CONTENT_URL + '/functions/v1/movie-trailer';
|
| 1497 |
const TRAILER_KEY = SUPABASE_ANON_KEY;
|
| 1498 |
|
| 1499 |
-
//
|
| 1500 |
-
const
|
| 1501 |
-
const TRANSLATED_KEY = JM_CONFIG.TRANSLATED_KEY;
|
| 1502 |
-
// movie-zilizotafsriwa2 — filamu zenye MP4 (draft/public kutoka admin); project ile ile ya CONTENT_URL.
|
| 1503 |
-
// Id zake zinaanza na 'n2-' ili zisigongane na za chanzo cha zamani.
|
| 1504 |
-
const TRANSLATED2_BASE = JM_CONFIG.CONTENT_URL + '/functions/v1/movie-zilizotafsriwa2';
|
| 1505 |
-
const TR2_PREFIX = 'n2-';
|
| 1506 |
-
const TR_DJ_NOISE = /\b(movies?|filamu|zote|zilizotafsiriwa|zilizotafsiri|imetafsiriwa|iliyotafsiriwa|tafsiriwa|kiswahili|swahili|kwa|mpya|kali|translated|new|all|series|full)\b/gi;
|
| 1507 |
function normDj(raw) { // jina safi la DJ (bila maneno ya ziada na bila tofauti za herufi kubwa/ndogo)
|
| 1508 |
const s = String(raw || '').replace(/\(.*?\)|\[.*?\]/g, ' ').replace(TR_DJ_NOISE, ' ').replace(/[|_\-\u2013\u2014:,.]+/g, ' ').replace(/\s+/g, ' ').trim();
|
| 1509 |
if (!s || /^dj$/i.test(s)) return '';
|
| 1510 |
-
|
|
|
|
| 1511 |
}
|
|
|
|
|
|
|
| 1512 |
// Model iliyofunzwa (train.py -> HF Model). Ikikosekana, app inafanya kazi kama kawaida (Trending = mpya zaidi).
|
|
|
|
| 1513 |
const TR_MODEL_URL = 'https://huggingface.co/jaynesmaxtv/translated-recommender/resolve/main/model.json';
|
| 1514 |
let trModelP = null;
|
| 1515 |
function loadTrModel() {
|
| 1516 |
if (!trModelP) trModelP = fetch(TR_MODEL_URL, { cache: 'no-cache' }).then(r => r.ok ? r.json() : null).catch(() => null);
|
| 1517 |
return trModelP;
|
| 1518 |
}
|
| 1519 |
-
function logTrPlay(id) { // rekodi uchezaji bila kuzuia player; kitambulisho cha kifaa ni cha nasibu (hakuna jina/email)
|
| 1520 |
-
if (!id) return;
|
| 1521 |
-
let dev = '';
|
| 1522 |
-
try { dev = localStorage.getItem('jm_dev') || ''; if (!dev) { dev = (crypto.randomUUID && crypto.randomUUID()) || (Date.now() + '-' + Math.random().toString(36).slice(2)); localStorage.setItem('jm_dev', dev); } } catch (_) {}
|
| 1523 |
-
fetch(TRANSLATED2_BASE + '?action=play', { method: 'POST', keepalive: true,
|
| 1524 |
-
headers: { apikey: SUPABASE_ANON_KEY, 'Content-Type': 'application/json' },
|
| 1525 |
-
body: JSON.stringify({ movie_id: String(id), device_id: dev }) }).catch(() => {});
|
| 1526 |
-
}
|
| 1527 |
// Rails za mlalo: Trending Now (Top 10, kwa model au mpya zaidi) -> New Releases -> kila DJ (DJ Mack kwanza) -> Series -> More to Watch
|
| 1528 |
function buildTranslatedSections(items, model) {
|
| 1529 |
const pop = (model && model.popularity) || {}, sections = [], covered = new Set();
|
|
@@ -1546,13 +1543,11 @@ function buildTranslatedSections(items, model) {
|
|
| 1546 |
if (more.length) sections.push({ title: t('tr_more'), items: more.slice(0, 40) });
|
| 1547 |
return sections;
|
| 1548 |
}
|
| 1549 |
-
async function fetchTranslatedMovie(id) { // -> { ok, error?, movie } kutoka
|
| 1550 |
-
const
|
| 1551 |
-
const
|
| 1552 |
-
|
| 1553 |
-
|
| 1554 |
-
const d = await r.json();
|
| 1555 |
-
return isNew ? { ok: r.ok && !d.error, error: d.error, movie: d } : d;
|
| 1556 |
}
|
| 1557 |
const PIXTVMAX_CATEGORY_SW = {
|
| 1558 |
'Sports': 'cat_sports', 'Movie Channels': 'cat_movies', 'News': 'cat_news',
|
|
@@ -2950,6 +2945,13 @@ const I18N_EXTRA10 = {
|
|
| 2950 |
fr: { jtv_next: 'Ensuite', jtv_schedule: 'Programme', jtv_down: 'JaynesTV est indisponible', tr_trending: 'Tendances actuelles', tr_new: 'Nouveautés', tr_more: 'À découvrir' }
|
| 2951 |
};
|
| 2952 |
Object.keys(I18N_EXTRA10).forEach(l => { I18N[l] = Object.assign(I18N[l] || {}, I18N_EXTRA10[l]); });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2953 |
function T(k, v) { return t(k, v); }
|
| 2954 |
// Maandishi yaliyoandikwa kwenye HTML kupitia data-i18n / data-i18n-ph / data-i18n-title
|
| 2955 |
function applyI18nAttrs() {
|
|
@@ -3833,25 +3835,78 @@ async function fetchTranslatedListRaw() {
|
|
| 3833 |
id: idPrefix + m.id, kind: 'translated', title: m.title,
|
| 3834 |
poster: m.thumb_url || m.poster_url || null, imgFallbackOn: true,
|
| 3835 |
subtitle: normDj(m.dj) || (m.category === 'series' ? 'Series' : 'Movie'), isSeries: m.category === 'series',
|
|
|
|
| 3836 |
});
|
| 3837 |
-
const
|
| 3838 |
-
|
| 3839 |
-
|
| 3840 |
-
|
| 3841 |
-
|
| 3842 |
-
|
| 3843 |
-
|
| 3844 |
-
|
| 3845 |
-
|
| 3846 |
-
|
| 3847 |
-
|
| 3848 |
-
|
| 3849 |
-
|
| 3850 |
-
const
|
| 3851 |
-
|
| 3852 |
-
|
| 3853 |
-
|
| 3854 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3855 |
}
|
| 3856 |
|
| 3857 |
async function loadTranslated() {
|
|
@@ -3859,7 +3914,8 @@ async function loadTranslated() {
|
|
| 3859 |
renderSkeletonRails(2);
|
| 3860 |
try {
|
| 3861 |
const [items, model] = await Promise.all([fetchTranslatedList(), loadTrModel()]);
|
| 3862 |
-
|
|
|
|
| 3863 |
} catch (e) {
|
| 3864 |
railsEl.innerHTML = '';
|
| 3865 |
railsEl.appendChild(stateBox(t('err_failed', { e: esc(e.message || t('err_generic')) }), true, loadTranslated));
|
|
@@ -4091,7 +4147,6 @@ function playTranslatedUrl(url, title, playlist, meta) {
|
|
| 4091 |
v.addEventListener('ended', () => { const c = window.__pcPlaylist; if (c && typeof c.next === 'function') c.next(); });
|
| 4092 |
// Tangazo la video kwanza (likishindikana/likiruka, filamu inaanza mara moja)
|
| 4093 |
v.src = url;
|
| 4094 |
-
try { logTrPlay(currentTranslatedDetail && currentTranslatedDetail.id); } catch (_) {}
|
| 4095 |
// Route ya player: #/translated/ID/play?se=..&ep=..
|
| 4096 |
try {
|
| 4097 |
const id = currentTranslatedDetail && currentTranslatedDetail.id;
|
|
|
|
| 1226 |
/* Nafasi ya kusogeza (scroll) ili kipengele chenye focus kisifichwe na topbar / nav */
|
| 1227 |
.poster,.cw-card,.tab-chip,.settings-row,.dq-item,.tr-ep,.cast-item{scroll-margin:110px 3vw 110px 3vw;}
|
| 1228 |
</style>
|
| 1229 |
+
<style>
|
| 1230 |
+
.tr-filter{margin:0 0 10px;}
|
| 1231 |
+
.tr-filter .tabs{padding:10px 16px 4px;}
|
| 1232 |
+
.tr-filter .tr-dj-row{padding-top:4px;}
|
| 1233 |
+
.tr-filter .tr-dj-row .tab-chip{font-size:12px; padding:6px 12px;}
|
| 1234 |
+
.tr-filter-note{padding:4px 16px 6px; font-size:12px; color:var(--muted);}
|
| 1235 |
+
</style>
|
| 1236 |
</head>
|
| 1237 |
<body>
|
| 1238 |
<div id="gate">
|
|
|
|
| 1503 |
const TRAILER_BASE = JM_CONFIG.CONTENT_URL + '/functions/v1/movie-trailer';
|
| 1504 |
const TRAILER_KEY = SUPABASE_ANON_KEY;
|
| 1505 |
|
| 1506 |
+
// Zilizotafsiriwa: chanzo kimoja (movie-translated-all) — n2-, ab-, abm- ids
|
| 1507 |
+
const TR_DJ_NOISE = /\b(movies?|filamu|zote|zilizotafsiriwa|zilizotafsiri|imetafsiriwa|iliyotafsiriwa|tafsiriwa|kiswahili|swahili|kwa|mpya|kali|translated|new|all|series|full|single|singo|action|cartoon|katuni|season|seasons|(?:19|20)\d{2})\b/gi;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1508 |
function normDj(raw) { // jina safi la DJ (bila maneno ya ziada na bila tofauti za herufi kubwa/ndogo)
|
| 1509 |
const s = String(raw || '').replace(/\(.*?\)|\[.*?\]/g, ' ').replace(TR_DJ_NOISE, ' ').replace(/[|_\-\u2013\u2014:,.]+/g, ' ').replace(/\s+/g, ' ').trim();
|
| 1510 |
if (!s || /^dj$/i.test(s)) return '';
|
| 1511 |
+
const name = s.split(' ').map(w => /^dj$/i.test(w) ? 'DJ' : w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(' ');
|
| 1512 |
+
return TR_DJ_ALIAS[name.toLowerCase()] || name;
|
| 1513 |
}
|
| 1514 |
+
// Majina tofauti ya DJ mmoja (andika kwa herufi ndogo upande wa kushoto)
|
| 1515 |
+
const TR_DJ_ALIAS = { 'dj blaki': 'DJ Black', 'blaki': 'DJ Black', 'black': 'DJ Black' };
|
| 1516 |
// Model iliyofunzwa (train.py -> HF Model). Ikikosekana, app inafanya kazi kama kawaida (Trending = mpya zaidi).
|
| 1517 |
+
const TRANSLATED_ALL = JM_CONFIG.CONTENT_URL + '/functions/v1/movie-translated-all';
|
| 1518 |
const TR_MODEL_URL = 'https://huggingface.co/jaynesmaxtv/translated-recommender/resolve/main/model.json';
|
| 1519 |
let trModelP = null;
|
| 1520 |
function loadTrModel() {
|
| 1521 |
if (!trModelP) trModelP = fetch(TR_MODEL_URL, { cache: 'no-cache' }).then(r => r.ok ? r.json() : null).catch(() => null);
|
| 1522 |
return trModelP;
|
| 1523 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1524 |
// Rails za mlalo: Trending Now (Top 10, kwa model au mpya zaidi) -> New Releases -> kila DJ (DJ Mack kwanza) -> Series -> More to Watch
|
| 1525 |
function buildTranslatedSections(items, model) {
|
| 1526 |
const pop = (model && model.popularity) || {}, sections = [], covered = new Set();
|
|
|
|
| 1543 |
if (more.length) sections.push({ title: t('tr_more'), items: more.slice(0, 40) });
|
| 1544 |
return sections;
|
| 1545 |
}
|
| 1546 |
+
async function fetchTranslatedMovie(id) { // -> { ok, error?, movie } kutoka movie-translated-all
|
| 1547 |
+
const r = await fetch(TRANSLATED_ALL + '?id=' + encodeURIComponent(id), { headers: { apikey: SUPABASE_ANON_KEY } });
|
| 1548 |
+
const d = await r.json().catch(() => ({}));
|
| 1549 |
+
if (!r.ok || !d.ok) return { ok: false, error: d.error || ('HTTP ' + r.status) };
|
| 1550 |
+
return d;
|
|
|
|
|
|
|
| 1551 |
}
|
| 1552 |
const PIXTVMAX_CATEGORY_SW = {
|
| 1553 |
'Sports': 'cat_sports', 'Movie Channels': 'cat_movies', 'News': 'cat_news',
|
|
|
|
| 2945 |
fr: { jtv_next: 'Ensuite', jtv_schedule: 'Programme', jtv_down: 'JaynesTV est indisponible', tr_trending: 'Tendances actuelles', tr_new: 'Nouveautés', tr_more: 'À découvrir' }
|
| 2946 |
};
|
| 2947 |
Object.keys(I18N_EXTRA10).forEach(l => { I18N[l] = Object.assign(I18N[l] || {}, I18N_EXTRA10[l]); });
|
| 2948 |
+
const I18N_EXTRA_TRF = {
|
| 2949 |
+
sw: { trf_all: 'Zote', trf_new: 'Mpya', trf_trend_movie: 'Movie Zinazovuma', trf_trend_series: 'Series Zinazovuma', trf_movie: 'Movie', trf_series: 'Series', trf_dj: 'Kwa DJ', trf_no_trend: 'Bado hakuna takwimu za kutosha za zinazovuma, tunaonyesha mpya zaidi kwanza.' },
|
| 2950 |
+
en: { trf_all: 'All', trf_new: 'New Releases', trf_trend_movie: 'Trending Movies', trf_trend_series: 'Trending Series', trf_movie: 'Movies', trf_series: 'Series', trf_dj: 'By DJ', trf_no_trend: 'Not enough viewing data yet, showing newest first.' },
|
| 2951 |
+
ar: { trf_all: 'الكل', trf_new: 'الجديد', trf_trend_movie: 'أفلام رائجة', trf_trend_series: 'مسلسلات رائجة', trf_movie: 'أفلام', trf_series: 'مسلسلات', trf_dj: 'حسب DJ', trf_no_trend: 'لا توجد بيانات مشاهدة كافية بعد، نعرض الأحدث أولاً.' },
|
| 2952 |
+
fr: { trf_all: 'Tout', trf_new: 'Nouveautés', trf_trend_movie: 'Films tendance', trf_trend_series: 'Séries tendance', trf_movie: 'Films', trf_series: 'Séries', trf_dj: 'Par DJ', trf_no_trend: "Pas encore assez de données, les plus récents d'abord." }
|
| 2953 |
+
};
|
| 2954 |
+
Object.keys(I18N_EXTRA_TRF).forEach(l => { I18N[l] = Object.assign(I18N[l] || {}, I18N_EXTRA_TRF[l]); });
|
| 2955 |
function T(k, v) { return t(k, v); }
|
| 2956 |
// Maandishi yaliyoandikwa kwenye HTML kupitia data-i18n / data-i18n-ph / data-i18n-title
|
| 2957 |
function applyI18nAttrs() {
|
|
|
|
| 3835 |
id: idPrefix + m.id, kind: 'translated', title: m.title,
|
| 3836 |
poster: m.thumb_url || m.poster_url || null, imgFallbackOn: true,
|
| 3837 |
subtitle: normDj(m.dj) || (m.category === 'series' ? 'Series' : 'Movie'), isSeries: m.category === 'series',
|
| 3838 |
+
added: m.created_at || m.updated_at || '',
|
| 3839 |
});
|
| 3840 |
+
const r = await fetch(TRANSLATED_ALL, { headers: { apikey: SUPABASE_ANON_KEY } });
|
| 3841 |
+
if (!r.ok) throw new Error(T('err_generic') + ' ' + r.status);
|
| 3842 |
+
const d = await r.json();
|
| 3843 |
+
if (!d.ok) throw new Error(d.error || 'Imekataa ombi.');
|
| 3844 |
+
return (d.movies || []).map(m => card(m, ''));
|
| 3845 |
+
}
|
| 3846 |
+
|
| 3847 |
+
// ── KUPANGA ZILIZOTAFSIRIWA: Zote / Mpya / Movie Zinazovuma / Series Zinazovuma / Movie / Series / Kwa DJ ──
|
| 3848 |
+
let trCache = null; // { items, model } -- kubadilisha kichujio hakupakui upya
|
| 3849 |
+
let trFilter = 'all', trDj = '';
|
| 3850 |
+
try { trFilter = sessionStorage.getItem('jm_tr_filter') || 'all'; trDj = sessionStorage.getItem('jm_tr_dj') || ''; } catch (_) {}
|
| 3851 |
+
const TR_FILTERS = ['all', 'new', 'trend_movie', 'trend_series', 'movie', 'series', 'dj'];
|
| 3852 |
+
function trDjGroups(items) { // DJ Mack kwanza, kisha DJ mwenye kazi nyingi zaidi
|
| 3853 |
+
const g = {};
|
| 3854 |
+
items.forEach(it => {
|
| 3855 |
+
const dj = String(it.subtitle || '').trim();
|
| 3856 |
+
if (!dj || dj === 'Series' || dj === 'Movie') return;
|
| 3857 |
+
(g[dj.toLowerCase()] = g[dj.toLowerCase()] || { name: dj, list: [] }).list.push(it);
|
| 3858 |
+
});
|
| 3859 |
+
return Object.values(g).sort((a, b) => (/mack/i.test(b.name) - /mack/i.test(a.name)) || b.list.length - a.list.length || a.name.localeCompare(b.name));
|
| 3860 |
+
}
|
| 3861 |
+
function trByNewest(list) { // mpya -> zamani kwa tarehe ya kuongezwa; zisizo na tarehe zinabaki kwa mpangilio wa seva
|
| 3862 |
+
return list.map((it, i) => [it, i])
|
| 3863 |
+
.sort((a, b) => (Date.parse(b[0].added) || 0) - (Date.parse(a[0].added) || 0) || a[1] - b[1]).map(x => x[0]);
|
| 3864 |
+
}
|
| 3865 |
+
function trTrending(list, model) { // kwa uchezaji halisi (model); zikipungua, zinaongezwa mpya zaidi bila namba
|
| 3866 |
+
const pop = (model && model.popularity) || {};
|
| 3867 |
+
const hot = list.filter(it => pop[it.id] > 0).sort((a, b) => pop[b.id] - pop[a.id]);
|
| 3868 |
+
const ranked = hot.slice(0, 30).map((it, i) => ({ ...it, rank: i < 10 ? i + 1 : undefined }));
|
| 3869 |
+
if (ranked.length < 10) {
|
| 3870 |
+
const have = new Set(ranked.map(it => it.id));
|
| 3871 |
+
trByNewest(list).forEach(it => { if (ranked.length < 30 && !have.has(it.id)) ranked.push(it); });
|
| 3872 |
+
}
|
| 3873 |
+
return { items: ranked, fallback: hot.length === 0 };
|
| 3874 |
+
}
|
| 3875 |
+
function renderTranslatedView() {
|
| 3876 |
+
if (!trCache) return;
|
| 3877 |
+
const { items, model } = trCache;
|
| 3878 |
+
const movies = items.filter(it => !it.isSeries), series = items.filter(it => it.isSeries);
|
| 3879 |
+
const groups = trDjGroups(items);
|
| 3880 |
+
if (!TR_FILTERS.includes(trFilter)) trFilter = 'all';
|
| 3881 |
+
if (trFilter === 'dj' && !groups.some(g => g.name === trDj)) trDj = groups[0] ? groups[0].name : '';
|
| 3882 |
+
let sections, grid = true, note = '';
|
| 3883 |
+
if (trFilter === 'new') sections = [{ title: t('tr_new'), items: trByNewest(items) }];
|
| 3884 |
+
else if (trFilter === 'trend_movie' || trFilter === 'trend_series') {
|
| 3885 |
+
const r = trTrending(trFilter === 'trend_movie' ? movies : series, model);
|
| 3886 |
+
if (r.fallback) note = t('trf_no_trend');
|
| 3887 |
+
sections = [{ title: t('trf_' + trFilter), items: r.items }];
|
| 3888 |
+
}
|
| 3889 |
+
else if (trFilter === 'movie') sections = [{ title: t('trf_movie'), items: trByNewest(movies) }];
|
| 3890 |
+
else if (trFilter === 'series') sections = [{ title: t('trf_series'), items: trByNewest(series) }];
|
| 3891 |
+
else if (trFilter === 'dj') {
|
| 3892 |
+
const g = groups.find(x => x.name === trDj);
|
| 3893 |
+
sections = g ? [{ title: g.name, items: trByNewest(g.list).map(it => ({ ...it, subtitle: it.isSeries ? 'Series' : '' })) }] : [];
|
| 3894 |
+
}
|
| 3895 |
+
else { sections = buildTranslatedSections(items, model); grid = false; }
|
| 3896 |
+
renderRails(sections, grid);
|
| 3897 |
+
const bar = document.createElement('div');
|
| 3898 |
+
bar.className = 'tr-filter';
|
| 3899 |
+
bar.innerHTML = `<div class="tabs">${TR_FILTERS.map(f => `<div class="tab-chip${f === trFilter ? ' active' : ''}" data-trf="${f}">${esc(t('trf_' + f))}</div>`).join('')}</div>` +
|
| 3900 |
+
(trFilter === 'dj' && groups.length ? `<div class="tabs tr-dj-row">${groups.map(g => `<div class="tab-chip${g.name === trDj ? ' active' : ''}" data-trdj="${esc(g.name)}">${esc(g.name)} · ${g.list.length}</div>`).join('')}</div>` : '') +
|
| 3901 |
+
(note ? `<div class="tr-filter-note">${esc(note)}</div>` : '');
|
| 3902 |
+
bar.onclick = (e) => {
|
| 3903 |
+
const c = e.target.closest('.tab-chip'); if (!c) return;
|
| 3904 |
+
if (c.dataset.trf) trFilter = c.dataset.trf; else if (c.dataset.trdj != null) trDj = c.dataset.trdj; else return;
|
| 3905 |
+
try { sessionStorage.setItem('jm_tr_filter', trFilter); sessionStorage.setItem('jm_tr_dj', trDj); } catch (_) {}
|
| 3906 |
+
renderTranslatedView();
|
| 3907 |
+
};
|
| 3908 |
+
railsEl.insertBefore(bar, railsEl.firstChild);
|
| 3909 |
+
bar.querySelectorAll('.tab-chip.active').forEach(c => { const row = c.parentElement; row.scrollLeft = c.offsetLeft - (row.clientWidth - c.offsetWidth) / 2; });
|
| 3910 |
}
|
| 3911 |
|
| 3912 |
async function loadTranslated() {
|
|
|
|
| 3914 |
renderSkeletonRails(2);
|
| 3915 |
try {
|
| 3916 |
const [items, model] = await Promise.all([fetchTranslatedList(), loadTrModel()]);
|
| 3917 |
+
trCache = { items, model };
|
| 3918 |
+
renderTranslatedView();
|
| 3919 |
} catch (e) {
|
| 3920 |
railsEl.innerHTML = '';
|
| 3921 |
railsEl.appendChild(stateBox(t('err_failed', { e: esc(e.message || t('err_generic')) }), true, loadTranslated));
|
|
|
|
| 4147 |
v.addEventListener('ended', () => { const c = window.__pcPlaylist; if (c && typeof c.next === 'function') c.next(); });
|
| 4148 |
// Tangazo la video kwanza (likishindikana/likiruka, filamu inaanza mara moja)
|
| 4149 |
v.src = url;
|
|
|
|
| 4150 |
// Route ya player: #/translated/ID/play?se=..&ep=..
|
| 4151 |
try {
|
| 4152 |
const id = currentTranslatedDetail && currentTranslatedDetail.id;
|