0;
var canB2 = !!(d.stream_urls && d.stream_urls.length);
var canGd = hasGd;
var canHls = !!d.hls_url;
this._prevServer = this.server;
// Fullscreen bisa native (document.fullscreenElement) ATAU
// mode fallback CSS Plyr (`.plyr--fullscreen-fallback`, dipakai
// WebView / browser tanpa Fullscreen API). Kalau hanya cek
// document.fullscreenElement, di mode fallback ini nilainya
// null -> re-enter tak pernah jalan -> keluar fullscreen.
this._wasFullscreen = !!(document.fullscreenElement
|| document.querySelector('.plyr--fullscreen-fallback'));
const c = document.getElementById('anime-player-container');
if (c) {
var spriteUrl = d.sprite_url ? d.sprite_url : null;
window.b2PlayerOptions = {
sources: d.stream_urls,
gdriveSources: gdSrcs,
episodeId: d.id,
prevUrl: d.prev_url,
nextUrl: d.next_url,
skipIntroAt: null,
posterUrl: d.poster_url,
title: epTitle,
slug: slug,
currentEp: d.episode_number,
episodes: window.b2PlayerOptions?.episodes || [],
epTotal: window.b2PlayerOptions?.epTotal || 0,
epPerPage: window.b2PlayerOptions?.epPerPage || 50,
epCurrentPage: window.b2PlayerOptions?.epCurrentPage || 1,
logoUrl: window.b2PlayerOptions?.logoUrl || null,
spriteUrl: spriteUrl,
};
var _pp = window.b2PlayerOptions.epPerPage || 52;
var _eps = window.b2PlayerOptions.episodes || [];
var _epIdx = _eps.findIndex(function(e) { return e.id === d.id; });
window.b2PlayerOptions.epCurrentPage = _epIdx >= 0 ? Math.floor(_epIdx / _pp) + 1 : 1;
}
this.gdriveSources = gdSrcs;
if (window.b2PlayerOptions) window.b2PlayerOptions.hlsUrl = d.hls_url || null;
// Resolve the target server BEFORE touching any player, otherwise the
// previous episode keeps playing inside a display:none frame (double audio).
var order = (this.server === 'hls') ? ['hls', 'b2', 'gdrive'] : ['b2', 'gdrive', 'hls'];
var picked = null;
for (var oi = 0; oi < order.length; oi++) {
if (order[oi] === 'b2' && canB2) { picked = 'b2'; break; }
if (order[oi] === 'gdrive' && canGd) { picked = 'gdrive'; break; }
if (order[oi] === 'hls' && canHls) { picked = 'hls'; break; }
}
if (!picked) picked = canB2 ? 'b2' : (canGd ? 'gdrive' : (canHls ? 'hls' : this.server));
this.server = picked;
this.pauseInactivePlayers();
// Player langsung mencoba primary GDrive. Kalau kena 403,
// player.js (_handleFailure) yang menampilkan overlay dan
// memicu mirror on-demand — jadi pindah episode tidak lagi
// tertahan menunggu mirror dibuat.
if (picked === 'hls' || (!canB2 && !canGd)) {
this.killDirectPlayer();
} else if (c) {
var gdNow = (picked === 'gdrive');
var srces = gdNow ? gdSrcs : d.stream_urls;
if (gdNow) this.gdriveLoaded = false; else this.b2Loaded = false;
if (c._player && c._player.switchSource) {
c._player.isGdrive = gdNow;
c._player.switchSource(
srces, d.prev_url, d.next_url, d.poster_url, epTitle,
slug, window.b2PlayerOptions.episodes, d.episode_number,
window.b2PlayerOptions.epCurrentPage, window.b2PlayerOptions.epPerPage,
window.b2PlayerOptions.epTotal, d.id, spriteUrl
);
const v = c.querySelector('#anime-video');
if (v) {
let _done = false;
const _ready = () => { if (_done) return; _done = true; if (gdNow) this.gdriveLoaded = true; else this.b2Loaded = true; };
v.addEventListener('playing', _ready, { once: true });
v.addEventListener('canplay', _ready, { once: true });
setTimeout(_ready, 8000);
} else { if (gdNow) this.gdriveLoaded = true; else this.b2Loaded = true; }
} else {
c.querySelectorAll('video').forEach((v) => this._hardStopMedia(v));
c.innerHTML = '';
this.$nextTick(() => {
if (gdNow) window.initAnimePlayer(c, Object.assign({}, window.b2PlayerOptions, { sources: srces, isGdrive: true }));
else window.initAnimePlayer(c, window.b2PlayerOptions);
if (gdNow) this.gdriveLoaded = true; else this.b2Loaded = true;
});
}
}
// HLS player: (re)source it only after the server is resolved.
if (this.server === 'hls') {
this.hlsLoaded = false;
const hc = document.getElementById('hls-player-container');
// A new episode is an explicit play intent -- unless the
// user paused while this switch was still in flight.
if (hc && (hc._hlsPauseEpoch || 0) === hcEp0) hc._hlsUserPaused = false;
if (!canHls) {
this.killHlsPlayer();
} else if (hc && typeof hc.switchHlsSource === 'function') {
hc.switchHlsSource(d.hls_url);
this.hlsLoaded = true;
} else {
this.$nextTick(() => this.loadHls());
}
} else {
this._pauseHls();
}
// 1. Release date
if (this.$refs.epReleaseDate) {
var dt = this.$refs.epReleaseDate;
if (d.formatted_release_date) {
dt.querySelector('span') ? dt.querySelector('span').textContent = d.formatted_release_date : dt.appendChild(document.createTextNode(d.formatted_release_date));
dt.style.display = '';
} else {
dt.style.display = 'none';
}
}
// 3. Duration
if (this.$refs.epDuration) {
if (d.duration) {
this.$refs.epDuration.querySelector('span').textContent = d.duration;
this.$refs.epDuration.style.display = '';
} else {
this.$refs.epDuration.style.display = 'none';
}
}
// 4. Description
if (this.$refs.epDescription) {
var descP = this.$refs.epDescription.querySelector('p');
if (descP) {
if (d.description) {
descP.innerHTML = '
Episode ' + epLabel + ' - ' + d.description;
this.$refs.epDescription.style.display = '';
} else {
this.$refs.epDescription.style.display = 'none';
}
}
}
// 5. Like button
var likeBtn = document.getElementById('like-btn');
if (likeBtn) {
likeBtn.dataset.episodeId = d.id;
likeBtn.dataset.liked = d.is_liked ? '1' : '0';
var lc = document.getElementById('like-count');
if (lc) lc.textContent = d.likes_count || '0';
var icon = likeBtn.querySelector('svg');
if (d.is_liked) {
likeBtn.classList.add('liked');
if (icon) icon.setAttribute('fill', 'currentColor');
} else {
likeBtn.classList.remove('liked');
if (icon) icon.setAttribute('fill', 'none');
}
}
// 7. Update current episode ID for pagination
this.currentEpisodeId = d.id;
// 9. HLS / GDrive / B2 tabs — source + player already resolved above
this.hasHls = canHls;
this.hasGdrive = canGd;
this.hasB2Stream = canB2;
if (this._wasFullscreen && this._prevServer !== this.server) {
const target = this._isDirect()
? document.getElementById('anime-player-container')
: document.getElementById('hls-player-container');
this._reenterFullscreen(target, 0);
}
var posterOverlays = document.querySelectorAll('.watch-player-frame [style*="background-image"]');
if (d.poster_url) {
for (var i = 0; i < posterOverlays.length; i++) {
posterOverlays[i].style.backgroundImage = 'url(\'' + d.poster_url + '\')';
}
}
// 10. Prev/Next buttons
if (this.$refs.prevBtn) {
if (d.prev_url) { this.$refs.prevBtn.href = d.prev_url; this.$refs.prevBtn.classList.remove('hidden'); }
else { this.$refs.prevBtn.classList.add('hidden'); }
}
if (this.$refs.nextBtn) {
if (d.next_url) { this.$refs.nextBtn.href = d.next_url; this.$refs.nextBtn.classList.remove('hidden'); }
else { this.$refs.nextBtn.classList.add('hidden'); }
}
// 11. Browser URL
history.pushState(null, '', '/anime/' + slug + '/episode/' + d.episode_number);
// 12. Breadcrumb episode
var breadcrumbEpisode = document.querySelector('#watch-breadcrumb .crumb-seg:last-child .crumb-label');
if (breadcrumbEpisode) {
breadcrumbEpisode.textContent = false ? 'Movie' : 'Ep ' + epLabel;
}
// 13. Episode chips active state
document.querySelectorAll('.ep-chip').forEach(function(el) {
el.classList.remove('active');
if (parseInt(el.dataset.ep) === d.episode_number) {
el.classList.add('active');
}
});
// 12b. Full grid items active state (showAllEpisodes)
document.querySelectorAll('.ep-btn, .ep-btn-sidebar').forEach(function(el) {
if (parseInt(el.dataset.ep) === d.episode_number) {
el.classList.add('bg-purple-600', 'text-white');
el.classList.remove('bg-gray-800', 'text-gray-400', 'border', 'border-gray-700/50', 'hover:bg-gray-700', 'bg-gray-700/50');
} else {
el.classList.remove('bg-purple-600', 'text-white');
el.classList.add('bg-gray-800', 'text-gray-400', 'border', 'border-gray-700/50', 'hover:bg-gray-700');
}
});
// 13. Sidebar episodes active state
document.querySelectorAll('.sidebar-ep-item').forEach(function(el) {
el.classList.remove('active', 'bg-purple-600/10');
el.classList.add('hover:bg-white/5');
if (parseInt(el.dataset.ep) === d.episode_number) {
el.classList.remove('hover:bg-white/5');
el.classList.add('active', 'bg-purple-600/10');
}
});
// 14. Repost button
var rpBtn = document.getElementById('repost-btn');
if (rpBtn) rpBtn.dataset.episodeId = d.id;
// 15. Download link
var dlLink = document.getElementById('download-link');
if (dlLink) dlLink.href = '/anime/' + slug + '/episode/' + d.episode_number + '/download';
// 16. Report forms
document.querySelectorAll('.report-form').forEach(function(f) {
f.action = '/episode/' + d.id + '/report';
});
// 17. Comments
if (d.comments_html) {
var csEl = document.getElementById('comment-section');
if (csEl) csEl.outerHTML = d.comments_html;
}
// 18. Episode Berikutnya
var nexEl = document.getElementById('next-episode-container');
if (nexEl) {
nexEl.innerHTML = d.next_episode_html || '';
nexEl.hidden = !(d.next_episode_html || '').trim();
}
// Safety net: only the resolved server may keep playing.
this.pauseInactivePlayers();
this._loading = false;
})
.catch(() => { this._loading = false; });
},
// Keluar dari fullscreen (native maupun fallback CSS) pada player
// selain `keep`.
_exitOtherFullscreens(keep) {
const keepPlayer = keep ? (keep._player ? keep._player.player : keep._hlsPlayer) : null;
const keepTarget = keepPlayer && keepPlayer.fullscreen ? keepPlayer.fullscreen.target : null;
['anime-player-container', 'hls-player-container'].forEach((id) => {
const oc = document.getElementById(id);
if (!oc || oc === keep) return;
const op = oc._player ? oc._player.player : oc._hlsPlayer;
try {
if (!op || !op.fullscreen || !op.fullscreen.active) return;
// Target fullscreen sama (`.player-fs-shell` dipakai bersama
// kedua player) -> JANGAN di-exit; itu justru menutup
// fullscreen yang sedang aktif.
if (keepTarget && op.fullscreen.target === keepTarget) return;
op.fullscreen.exit();
} catch (e) {}
});
},
_reenterFullscreen(container, attempts) {
if (!container) return;
attempts = attempts || 0;
if (attempts > 60) return;
const retry = (delay) => setTimeout(() => this._reenterFullscreen(container, attempts + 1), delay || 200);
const pe = container.querySelector('.plyr');
const p = container._player ? (container._player.player || null) : (container._hlsPlayer || null);
if (!p || !p.fullscreen) { retry(); return; }
// Sudah fullscreen di player ini (native atau fallback CSS)?
if (p.fullscreen.active) {
const nf = document.fullscreenElement;
if (!nf || !pe || nf === pe || pe.contains(nf) || nf.contains(pe)) return;
}
// Player yang baru ditinggalkan harus keluar dulu -- baik native
// (document.fullscreenElement) maupun fallback CSS (class), karena
// di mode fallback document.fullscreenElement selalu null.
this._exitOtherFullscreens(container);
// Native: tunggu sampai browser benar-benar melepas fullscreen.
if (document.fullscreenElement) { retry(); return; }
// Frame tujuan harus sudah ter-render (Alpine x-show), kalau tidak
// fullscreen ke elemen yang belum tampil akan kosong.
const frame = container.closest('.watch-player-frame');
if (frame && window.getComputedStyle(frame).display === 'none') { retry(); return; }
if (!pe) { retry(); return; }
// Plyr's fullscreen.enter() TIDAK mengembalikan promise -> jangan pakai
// .catch() (dulu melempar TypeError dan bikin re-enter tak pernah jalan).
// requestFullscreen juga bisa ditolak (butuh user gesture), jadi hasilnya
// dipantau lewat retry, bukan dianggap sukses begitu saja.
try {
if (!p.fullscreen.active) p.fullscreen.enter();
} catch (e) {
retry(300);
return;
}
retry(300);
},
loadPage(page) {
if (this._loadingGrid) return;
this._loadingGrid = true;
const params = new URLSearchParams({
page: page || 1,
ep: this.currentEpisodeId,
sort: this.epSort,
search: this.epSearch
});
fetch('/anime/stein-gate-subtitle-indonesia/episodes/grid?' + params.toString())
.then(r => r.json())
.then(d => {
if (this.$refs.sidebarEpList) this.$refs.sidebarEpList.innerHTML = d.sidebar_episodes;
if (this.$refs.sidebarPag) this.$refs.sidebarPag.innerHTML = d.pagination;
this._loadingGrid = false;
})
.catch(() => { this._loadingGrid = false; });
},
applyEpSearch() {
this.loadPage(1);
}
}"
class="">
EP 23 - Open the Steins Gate
Info
Komentar (0)
Repost
Download
Report
Laporkan Masalah
Pilih alasan untuk melaporkan episode ini.
Batal
Laporkan Masalah
Jelaskan masalah yang kamu temui agar tim kami bisa memperbaikinya.
Share
Steins; Gerbang
Steins;Gate - Self memproklamirkan ilmuwan gila Okabe Rintarou tinggal di sebuah ruangan kecil di Akihabara, di mana ia menciptakan "alat masa depan" dengan sesama anggota lab Shiina Mayuri, teman udara-nya, dan Hashida Itaru, seorang hacker otaku. Ketiga melewati waktu dengan bermain-main dengan penciptaan terbaru mereka, "Mikrowave Telepon" yang dapat dikendalikan melalui pesan teks. Anggota lab segera menghadapi serangkaian kejadian misterius yang mengarah pada penemuan yang berubah-ubah: Microwave Telepon dapat mengirim email ke masa lalu dan dengan demikian mengubah sejarah. Diadaptasi dari kritis diakui novel visual oleh 5pb. dan Nitroplus, Steins; Gerbang mengambil Okabe ke kedalaman teori ilmiah dan putus asa manusia karena ia menghadapi konsekuensi mengerikan mengubah masa lalu.
Nonton Steins;Gate Episode 23 Subtitle Indonesia secara online dengan berbagai pilihan kualitas video, mulai dari 360p, 480p, 720p hingga 1080p. Pilih server dan resolusi yang sesuai untuk menikmati episode Steins;Gate dengan subtitle Indonesia di perangkat kamu.
Frontier Works
Steins;Gate episode 23 subtitle indonesia, download Steins;Gate episode 23 subtitle indonesia, unduh Steins;Gate episode 23 subtitle indonesia, streaming Steins;Gate episode 23 subtitle indonesia, nonton Steins;Gate episode 23 subtitle indonesia, anime Steins;Gate episode 23 subtitle indonesia, download anime Steins;Gate episode 23 subtitle indonesia, unduh anime Steins;Gate episode 23 subtitle indonesia, streaming anime Steins;Gate episode 23 subtitle indonesia, nonton anime Steins;Gate episode 23 subtitle indonesia, Steins;Gate episode 23 sub indo, download Steins;Gate episode 23 sub indo, unduh Steins;Gate episode 23 sub indo, streaming Steins;Gate episode 23 sub indo, nonton Steins;Gate episode 23 sub indo, anime Steins;Gate episode 23 sub indo, download anime Steins;Gate episode 23 sub indo, unduh anime Steins;Gate episode 23 sub indo, streaming anime Steins;Gate episode 23 sub indo, nonton anime Steins;Gate episode 23 sub indo, Steins;Gate episode 23 takarir indonesia, download Steins;Gate episode 23 takarir indonesia, unduh Steins;Gate episode 23 takarir indonesia, streaming Steins;Gate episode 23 takarir indonesia, nonton Steins;Gate episode 23 takarir indonesia, anime Steins;Gate episode 23 takarir indonesia, download anime Steins;Gate episode 23 takarir indonesia, unduh anime Steins;Gate episode 23 takarir indonesia, streaming anime Steins;Gate episode 23 takarir indonesia, nonton anime Steins;Gate episode 23 takarir indonesia, Steins;Gate episode 23 takarir indo, download Steins;Gate episode 23 takarir indo, unduh Steins;Gate episode 23 takarir indo, streaming Steins;Gate episode 23 takarir indo, nonton Steins;Gate episode 23 takarir indo, anime Steins;Gate episode 23 takarir indo, download anime Steins;Gate episode 23 takarir indo, unduh anime Steins;Gate episode 23 takarir indo, streaming anime Steins;Gate episode 23 takarir indo, nonton anime Steins;Gate episode 23 takarir indo, Steins;Gate episode 23 subtitle indo, download Steins;Gate episode 23 subtitle indo, unduh Steins;Gate episode 23 subtitle indo, streaming Steins;Gate episode 23 subtitle indo, nonton Steins;Gate episode 23 subtitle indo, anime Steins;Gate episode 23 subtitle indo, download anime Steins;Gate episode 23 subtitle indo, unduh anime Steins;Gate episode 23 subtitle indo, streaming anime Steins;Gate episode 23 subtitle indo, nonton anime Steins;Gate episode 23 subtitle indo
Komentar (0)
atau untuk berkomentar.
Belum ada komentar. Jadilah yang pertama!