Tarik untuk refresh

Memuat...

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) { var isMovieAnime = false; breadcrumbEpisode.textContent = isMovieAnime ? '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/black-clover/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 149 - Two Things We Need to Find

Laporkan Masalah

Pilih alasan untuk melaporkan episode ini.

Laporkan Masalah

Jelaskan masalah yang kamu temui agar tim kami bisa memperbaikinya.

Semanggi Hitam

8.2 · TV · Complete
Black Clover - In a world where magic is everything, Asta and Yuno are both found abandoned at a church on the same day. While Yuno is gifted with exceptional magical powers, Asta is the only one in this world without any. At the age of fifteen, both receive grimoires, magic books that amplify their holder’s magic. Asta’s is a rare Grimoire of Anti-Magic that negates and repels his opponent’s spells. Being opposite but good rivals, Yuno and Asta are ready for the hardest of challenges to achieve their common dream: to be the Wizard King. Giving up is never an option!

(Source: Crunchyroll)

Nonton Black Clover Episode 149 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 Black Clover dengan subtitle Indonesia di perangkat kamu.

Studio Pierrot

Komentar (0)

atau untuk berkomentar.

Belum ada komentar. Jadilah yang pertama!

Pilih lagu untuk diputar

· NC

Belum ada theme songs

Daftar Episode

EP 105

EP 105

Smiles, Tears

EP 106

EP 106

Path of Revenge, Path of Atonement

EP 107

EP 107

The Battle for Clover Castle

EP 108

EP 108

Battlefield Dancer

EP 109

EP 109

Spatial Mage Brothers

EP 110

EP 110

The Raging Bull Joins the Showdown!!

EP 111

EP 111

The Eyes in the Mirror

EP 112

EP 112

Humans Who Can Be Trusted

EP 113

EP 113

Storming the Shadow Palace

EP 114

EP 114

The Final Invaders

EP 115

EP 115

Mastermind

EP 116

EP 116

The Ultimate Natural Enemy

EP 117

EP 117

Breaking the Seal

EP 118

EP 118

A Reunion Across Time and Space

EP 119

EP 119

The Final Attack

EP 120

EP 120

Dawn

EP 121

EP 121

Three Problems

EP 122

EP 122

As Pitch Black as It Gets

EP 123

EP 123

Nero Reminisces... Part One

EP 124

EP 124

Nero Reminisces... Part Two

EP 125

EP 125

Return

EP 126

EP 126

The Blue Rose's Confession

EP 127

EP 127

Clues

EP 128

EP 128

To the Heart Kingdom!

EP 129

EP 129

The Devil Megicula

EP 130

EP 130

The New Magic Knight Squad Captains' Meeting

EP 131

EP 131

A New Resolve

EP 132

EP 132

The Lion Awakens

EP 133

EP 133

The Lion Awakens, Continued

EP 134

EP 134

Those Who Have Been Gathered

EP 135

EP 135

The One Who Has My Heart, My Mind, And Soul

EP 136

EP 136

A Black Deep-Sea Story

EP 137

EP 137

Charmy's Century of Hunger, Gordon's Millennium of Loneliness

EP 138

EP 138

In Zara's Footsteps

EP 139

EP 139

A Witch's Homecoming

EP 140

EP 140

A Favor For Julius

EP 141

EP 141

The Golden Family

EP 142

EP 142

Those Remaining

EP 143

EP 143

The Tilted Scale

EP 144

EP 144

Those Who Wish to Destroy Devils

EP 145

EP 145

Rescue

EP 146

EP 146

Those Who Worship The Devil

EP 147

EP 147

Prepared to Die

EP 148

EP 148

Becoming the Light That Shines Through the Darkness

EP 149

EP 149

Two Things We Need to Find

EP 150

EP 150

The Maidens' Challenge

EP 151

EP 151

Clash! The Battle of the Magic Knights Squad Captains

EP 152

EP 152

To Tomorrow!

EP 153

EP 153

The Chosen Ones

EP 154

EP 154

Vice Captain Langris Vaude

EP 155

EP 155

The 5 Spirit Guardians

EP 156

EP 156

Awakening Powers

atau login dengan email

Lupa password?
atau daftar dengan email

Username ini sudah dipakai. Pilih username lain.

Hanya huruf kecil, angka, dan underscore (_) tanpa spasi.

Username tersedia!