mirror of
https://github.com/JustAnimeCore/JustAnime.git
synced 2026-04-17 13:51:44 +00:00
resolved servers
This commit is contained in:
14
.env.example
14
.env.example
@@ -1,15 +1,3 @@
|
||||
#Refer https://github.com/itzzzme/anime-api to host your backend API
|
||||
VITE_API_URL=<your_hosted_api>/api
|
||||
|
||||
#Refer this gist to setup proxy server https://gist.github.com/itzzzme/180813be2c7b45eedc8ce8344c8dea3b
|
||||
VITE_PROXY_URL=<proxy_server_name>/?url=
|
||||
|
||||
#Refer https://github.com/itzzzme/m3u8proxy to host you m3u8 proxy server though it's optional but if you don't set it up you may get CORS error for some servers if you set up from the given repo then only the url structure will look like this
|
||||
VITE_M3U8_PROXY_URL=<m3u8_proxy_server_name>/m3u8-proxy?url=
|
||||
|
||||
#totaly optional / if you don't want to setup worker just change the code of getQtip.utils.js following the pattern of any other utils file
|
||||
VITE_WORKER_URL=https://worker1.workers.dev,https://worker2.workers.dev,https://worker3.workers.dev,...
|
||||
|
||||
VITE_BASE_IFRAME_URL=https://megaplay.buzz/stream/s-2
|
||||
|
||||
VITE_BASE_IFRAME_URL_2=https://vidwish.live/stream/s-2
|
||||
VITE_HD_1_PROXY_URL=<hd_1_anime_paradise>/m3u8-proxy?url=
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable no-empty */
|
||||
/* eslint-disable no-unused-vars */
|
||||
/* eslint-disable react/prop-types */
|
||||
import Hls from "hls.js";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
@@ -28,20 +30,22 @@ import website_name from "@/src/config/website";
|
||||
import getChapterStyles from "./getChapterStyle";
|
||||
import artplayerPluginHlsControl from "artplayer-plugin-hls-control";
|
||||
import artplayerPluginUploadSubtitle from "./artplayerPluginUploadSubtitle";
|
||||
import { getTitle } from "@/src/utils/title.utils";
|
||||
|
||||
Artplayer.LOG_VERSION = false;
|
||||
Artplayer.CONTEXTMENU = false;
|
||||
|
||||
const KEY_CODES = {
|
||||
M: "m",
|
||||
I: "i",
|
||||
F: "f",
|
||||
V: "v",
|
||||
SPACE: " ",
|
||||
ARROW_UP: "arrowup",
|
||||
ARROW_DOWN: "arrowdown",
|
||||
ARROW_RIGHT: "arrowright",
|
||||
ARROW_LEFT: "arrowleft",
|
||||
M: "KeyM",
|
||||
I: "KeyI",
|
||||
F: "KeyF",
|
||||
V: "KeyV",
|
||||
SPACE: "Space",
|
||||
SPACE_LEGACY: "Spacebar",
|
||||
ARROW_UP: "ArrowUp",
|
||||
ARROW_DOWN: "ArrowDown",
|
||||
ARROW_RIGHT: "ArrowRight",
|
||||
ARROW_LEFT: "ArrowLeft",
|
||||
};
|
||||
|
||||
export default function Player({
|
||||
@@ -59,17 +63,15 @@ export default function Player({
|
||||
animeInfo,
|
||||
episodeNum,
|
||||
streamInfo,
|
||||
serverName,
|
||||
activeServerName,
|
||||
}) {
|
||||
const artRef = useRef(null);
|
||||
const leftAtRef = useRef(0);
|
||||
const boundKeydownRef = useRef(null);
|
||||
const proxy = import.meta.env.VITE_PROXY_URL;
|
||||
const m3u8proxy = import.meta.env.VITE_M3U8_PROXY_URL?.split(",") || [];
|
||||
const m3u8proxyHD3 = import.meta.env.VITE_M3U8_PROXY_HD3;
|
||||
const [currentEpisodeIndex, setCurrentEpisodeIndex] = useState(
|
||||
episodes?.findIndex(
|
||||
(episode) => episode.id.match(/ep=(\d+)/)?.[1] === episodeId
|
||||
)
|
||||
episodes?.findIndex((episode) => episode.id.match(/ep=(\d+)/)?.[1] === episodeId)
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -80,11 +82,10 @@ export default function Player({
|
||||
setCurrentEpisodeIndex(newIndex);
|
||||
}
|
||||
}, [episodeId, episodes]);
|
||||
|
||||
useEffect(() => {
|
||||
const applyChapterStyles = () => {
|
||||
const existingStyles = document.querySelectorAll(
|
||||
"style[data-chapter-styles]"
|
||||
);
|
||||
const existingStyles = document.querySelectorAll("style[data-chapter-styles]");
|
||||
existingStyles.forEach((style) => style.remove());
|
||||
const styleElement = document.createElement("style");
|
||||
styleElement.setAttribute("data-chapter-styles", "true");
|
||||
@@ -112,18 +113,13 @@ export default function Player({
|
||||
|
||||
art.on("destroy", () => hls.destroy());
|
||||
|
||||
// hls.on(Hls.Events.ERROR, (event, data) => {
|
||||
// console.error("HLS.js error:", data);
|
||||
// });
|
||||
video.addEventListener("timeupdate", () => {
|
||||
const currentTime = Math.round(video.currentTime);
|
||||
const duration = Math.round(video.duration);
|
||||
if (duration > 0 && currentTime >= duration) {
|
||||
art.pause();
|
||||
if (currentEpisodeIndex < episodes?.length - 1 && autoNext) {
|
||||
playNext(
|
||||
episodes[currentEpisodeIndex + 1].id.match(/ep=(\d+)/)?.[1]
|
||||
);
|
||||
playNext(episodes[currentEpisodeIndex + 1].id.match(/ep=(\d+)/)?.[1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -135,9 +131,7 @@ export default function Player({
|
||||
if (duration > 0 && currentTime >= duration) {
|
||||
art.pause();
|
||||
if (currentEpisodeIndex < episodes?.length - 1 && autoNext) {
|
||||
playNext(
|
||||
episodes[currentEpisodeIndex + 1].id.match(/ep=(\d+)/)?.[1]
|
||||
);
|
||||
playNext(episodes[currentEpisodeIndex + 1].id.match(/ep=(\d+)/)?.[1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -157,29 +151,76 @@ export default function Player({
|
||||
return chapters;
|
||||
};
|
||||
|
||||
const isEditableElement = (el) => {
|
||||
if (!el) return false;
|
||||
const tagName = el.tagName?.toLowerCase();
|
||||
if (tagName === "input" || tagName === "textarea" || el.isContentEditable) return true;
|
||||
if (el.closest) {
|
||||
const editable = el.closest("input, textarea, [contenteditable='true']");
|
||||
return !!editable;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const handleKeydown = (event, art) => {
|
||||
const tagName = event.target.tagName.toLowerCase();
|
||||
const container = artRef.current;
|
||||
if (!container || !art) return;
|
||||
|
||||
if (tagName === "input" || tagName === "textarea") return;
|
||||
const target = event.target;
|
||||
if (isEditableElement(target)) return;
|
||||
|
||||
switch (event.key.toLowerCase()) {
|
||||
const eventIsInsidePlayer =
|
||||
container.contains(target) || container.contains(document.activeElement);
|
||||
|
||||
if (!eventIsInsidePlayer) return;
|
||||
|
||||
const code = event.code;
|
||||
|
||||
switch (code) {
|
||||
case KEY_CODES.M:
|
||||
art.muted = !art.muted;
|
||||
break;
|
||||
case KEY_CODES.I:
|
||||
art.pip = !art.pip;
|
||||
break;
|
||||
case KEY_CODES.F:
|
||||
case KEY_CODES.F: {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
art.fullscreen = !art.fullscreen;
|
||||
|
||||
const container = artRef.current;
|
||||
const doc = document;
|
||||
const fsEl =
|
||||
doc.fullscreenElement ||
|
||||
doc.webkitFullscreenElement ||
|
||||
doc.mozFullScreenElement ||
|
||||
doc.msFullscreenElement;
|
||||
|
||||
if (fsEl && (fsEl === container || container.contains(fsEl))) {
|
||||
if (doc.exitFullscreen) doc.exitFullscreen();
|
||||
else if (doc.webkitExitFullscreen) doc.webkitExitFullscreen();
|
||||
else if (doc.mozCancelFullScreen) doc.mozCancelFullScreen();
|
||||
else if (doc.msExitFullscreen) doc.msExitFullscreen();
|
||||
} else {
|
||||
if (container.requestFullscreen) container.requestFullscreen();
|
||||
else if (container.webkitRequestFullscreen) container.webkitRequestFullscreen();
|
||||
else if (container.mozRequestFullScreen) container.mozRequestFullScreen();
|
||||
else if (container.msRequestFullscreen) container.msRequestFullscreen();
|
||||
}
|
||||
|
||||
try {
|
||||
art.fullscreen = !art.fullscreen;
|
||||
} catch (e) {
|
||||
// ignore if art not available
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEY_CODES.V:
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
art.subtitle.show = !art.subtitle.show;
|
||||
break;
|
||||
case KEY_CODES.SPACE:
|
||||
case KEY_CODES.SPACE_LEGACY:
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
art.playing ? art.pause() : art.play();
|
||||
@@ -211,20 +252,34 @@ export default function Player({
|
||||
|
||||
useEffect(() => {
|
||||
if (!streamUrl || !artRef.current) return;
|
||||
|
||||
const iframeUrl = streamInfo?.streamingLink?.iframe;
|
||||
const headers = {};
|
||||
headers.referer = new URL(iframeUrl).origin + "/";
|
||||
const finalProxy = (serverName === "hd-3" && m3u8proxyHD3)
|
||||
? m3u8proxyHD3
|
||||
const headers = {
|
||||
referer: iframeUrl ? new URL(iframeUrl).origin + "/" : window.location.origin + "/",
|
||||
};
|
||||
|
||||
const container = artRef.current;
|
||||
let fullscreenRefocusTimeout = null;
|
||||
|
||||
try {
|
||||
if (!container.hasAttribute("tabindex")) container.setAttribute("tabindex", "0");
|
||||
else {
|
||||
const current = parseInt(container.getAttribute("tabindex"), 10);
|
||||
if (isNaN(current) || current < 0) container.setAttribute("tabindex", "0");
|
||||
}
|
||||
container.style.outline = "none";
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
const hd1Proxy = import.meta.env.VITE_HD_1_PROXY_URL;
|
||||
const currentProxy = (activeServerName === "HD-1" && hd1Proxy)
|
||||
? hd1Proxy
|
||||
: m3u8proxy[Math.floor(Math.random() * m3u8proxy?.length)];
|
||||
console.log(finalProxy +
|
||||
encodeURIComponent(streamUrl) +
|
||||
"&headers=" +
|
||||
encodeURIComponent(JSON.stringify(headers)));
|
||||
|
||||
const art = new Artplayer({
|
||||
url:
|
||||
finalProxy +
|
||||
currentProxy +
|
||||
encodeURIComponent(streamUrl) +
|
||||
"&headers=" +
|
||||
encodeURIComponent(JSON.stringify(headers)),
|
||||
@@ -245,8 +300,8 @@ export default function Player({
|
||||
fastForward: true,
|
||||
aspectRatio: true,
|
||||
moreVideoAttr: {
|
||||
crossOrigin: 'anonymous',
|
||||
preload: 'none',
|
||||
crossOrigin: "anonymous",
|
||||
preload: "none",
|
||||
playsInline: true,
|
||||
},
|
||||
plugins: [
|
||||
@@ -374,13 +429,55 @@ export default function Player({
|
||||
},
|
||||
customType: { m3u8: playM3u8 },
|
||||
});
|
||||
|
||||
art.on("resize", () => {
|
||||
art.subtitle.style({
|
||||
fontSize:
|
||||
(art.width > 500 ? art.width * 0.02 : art.width * 0.03) + "px",
|
||||
fontSize: (art.width > 500 ? art.width * 0.02 : art.width * 0.03) + "px",
|
||||
});
|
||||
});
|
||||
|
||||
const refocusIfNeeded = (delay = 30) => {
|
||||
try {
|
||||
if (!container) return;
|
||||
const active = document.activeElement;
|
||||
if (!container.contains(active)) {
|
||||
fullscreenRefocusTimeout = setTimeout(() => {
|
||||
try {
|
||||
container.focus();
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
|
||||
const onFullscreenChange = () => {
|
||||
if (!document.fullscreenElement && !document.webkitIsFullScreen && !document.mozFullScreen && !document.msFullscreenElement) {
|
||||
refocusIfNeeded(40);
|
||||
} else {
|
||||
refocusIfNeeded(20);
|
||||
}
|
||||
};
|
||||
|
||||
// vendor event wrappers
|
||||
const fullscreenEvents = [
|
||||
"fullscreenchange",
|
||||
"webkitfullscreenchange",
|
||||
"mozfullscreenchange",
|
||||
"MSFullscreenChange",
|
||||
];
|
||||
fullscreenEvents.forEach((ev) => document.addEventListener(ev, onFullscreenChange));
|
||||
|
||||
art.on("ready", () => {
|
||||
try {
|
||||
container.focus();
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
const continueWatchingList = JSON.parse(localStorage.getItem("continueWatching")) || [];
|
||||
const currentEntry = continueWatchingList.find((item) => item.episodeId === episodeId);
|
||||
if (currentEntry?.leftAt) art.currentTime = currentEntry.leftAt;
|
||||
@@ -393,7 +490,15 @@ export default function Player({
|
||||
art.layers[website_name].style.opacity = 0;
|
||||
}, 2000);
|
||||
|
||||
const defaultSubtitle = subtitles?.find((sub) => sub.label.toLowerCase() === "english");
|
||||
const subs = (subtitles || []).map((s) => ({ ...s }));
|
||||
|
||||
for (const sub of subs) {
|
||||
const encodedUrl = encodeURIComponent(sub.file);
|
||||
const encodedHeaders = encodeURIComponent(JSON.stringify(headers));
|
||||
sub.file = `${proxy}${encodedUrl}&headers=${encodedHeaders}`;
|
||||
}
|
||||
|
||||
const defaultSubtitle = subs?.find((sub) => sub.label.toLowerCase() === "english");
|
||||
if (defaultSubtitle) {
|
||||
art.subtitle.switch(defaultSubtitle.file, {
|
||||
name: defaultSubtitle.label,
|
||||
@@ -402,12 +507,38 @@ export default function Player({
|
||||
}
|
||||
|
||||
const skipRanges = [
|
||||
...(intro.start != null && intro.end != null ? [[intro.start + 1, intro.end - 1]] : []),
|
||||
...(outro.start != null && outro.end != null ? [[outro.start + 1, outro.end]] : []),
|
||||
...(intro?.start != null && intro?.end != null ? [[intro.start + 1, intro.end - 1]] : []),
|
||||
...(outro?.start != null && outro?.end != null ? [[outro.start + 1, outro.end]] : []),
|
||||
];
|
||||
autoSkipIntro && art.plugins.add(autoSkip(skipRanges));
|
||||
|
||||
document.addEventListener("keydown", (event) => handleKeydown(event, art));
|
||||
const boundKeydown = (event) => handleKeydown(event, art);
|
||||
boundKeydownRef.current = boundKeydown;
|
||||
document.addEventListener("keydown", boundKeydown);
|
||||
|
||||
const focusOnPointerDown = () => {
|
||||
try {
|
||||
container.focus();
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
container.addEventListener("pointerdown", focusOnPointerDown, { passive: true });
|
||||
|
||||
const onWindowFocus = () => refocusIfNeeded(30);
|
||||
window.addEventListener("focus", onWindowFocus);
|
||||
|
||||
art.on("destroy", () => {
|
||||
try {
|
||||
document.removeEventListener("keydown", boundKeydown);
|
||||
} catch (e) { }
|
||||
try {
|
||||
container.removeEventListener("pointerdown", focusOnPointerDown);
|
||||
} catch (e) { }
|
||||
try {
|
||||
window.removeEventListener("focus", onWindowFocus);
|
||||
} catch (e) { }
|
||||
});
|
||||
|
||||
art.subtitle.style({
|
||||
fontSize: (art.width > 500 ? art.width * 0.02 : art.width * 0.03) + "px",
|
||||
@@ -420,6 +551,7 @@ export default function Player({
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const $rewind = art.layers["rewind"];
|
||||
const $forward = art.layers["forward"];
|
||||
Artplayer.utils.isMobile &&
|
||||
@@ -438,10 +570,11 @@ export default function Player({
|
||||
art.layers["forwardIcon"].style.opacity = 0;
|
||||
}, 300);
|
||||
});
|
||||
if (subtitles?.length > 0) {
|
||||
|
||||
if (subs?.length > 0) {
|
||||
const defaultEnglishSub =
|
||||
subtitles.find((sub) => sub.label.toLowerCase() === "english" && sub.default) ||
|
||||
subtitles.find((sub) => sub.label.toLowerCase() === "english");
|
||||
subs.find((sub) => sub.label.toLowerCase() === "english" && sub.default) ||
|
||||
subs.find((sub) => sub.label.toLowerCase() === "english");
|
||||
|
||||
art.setting.add({
|
||||
name: "captions",
|
||||
@@ -459,7 +592,7 @@ export default function Player({
|
||||
return !item.switch;
|
||||
},
|
||||
},
|
||||
...subtitles.map((sub) => ({
|
||||
...subs.map((sub) => ({
|
||||
default: sub.label.toLowerCase() === "english" && sub === defaultEnglishSub,
|
||||
html: sub.label,
|
||||
url: sub.file,
|
||||
@@ -477,32 +610,42 @@ export default function Player({
|
||||
if (art && art.destroy) {
|
||||
art.destroy(false);
|
||||
}
|
||||
document.removeEventListener("keydown", handleKeydown);
|
||||
const continueWatching = JSON.parse(localStorage.getItem("continueWatching")) || [];
|
||||
const newEntry = {
|
||||
id: animeInfo?.id,
|
||||
data_id: animeInfo?.data_id,
|
||||
episodeId,
|
||||
episodeNum,
|
||||
adultContent: animeInfo?.adultContent,
|
||||
poster: animeInfo?.poster,
|
||||
title: animeInfo?.title,
|
||||
japanese_title: animeInfo?.japanese_title,
|
||||
leftAt: leftAtRef.current,
|
||||
};
|
||||
|
||||
if (!newEntry.data_id) return;
|
||||
|
||||
const existingIndex = continueWatching.findIndex((item) => item.data_id === newEntry.data_id);
|
||||
if (existingIndex !== -1) {
|
||||
continueWatching[existingIndex] = newEntry;
|
||||
} else {
|
||||
continueWatching.push(newEntry);
|
||||
fullscreenEvents.forEach((ev) => document.removeEventListener(ev, onFullscreenChange));
|
||||
if (boundKeydownRef.current) {
|
||||
try {
|
||||
document.removeEventListener("keydown", boundKeydownRef.current);
|
||||
} catch (e) { }
|
||||
boundKeydownRef.current = null;
|
||||
}
|
||||
if (fullscreenRefocusTimeout) clearTimeout(fullscreenRefocusTimeout);
|
||||
|
||||
try {
|
||||
const continueWatching = JSON.parse(localStorage.getItem("continueWatching")) || [];
|
||||
const newEntry = {
|
||||
id: animeInfo?.id,
|
||||
data_id: animeInfo?.data_id,
|
||||
episodeId,
|
||||
episodeNum,
|
||||
adultContent: animeInfo?.adultContent,
|
||||
poster: animeInfo?.poster,
|
||||
title: getTitle(animeInfo, "EN"),
|
||||
japanese_title: getTitle(animeInfo, "JP"),
|
||||
leftAt: leftAtRef.current,
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
|
||||
if (!newEntry.data_id) return;
|
||||
|
||||
const filtered = continueWatching.filter((item) => item.data_id !== newEntry.data_id);
|
||||
filtered.unshift(newEntry);
|
||||
localStorage.setItem("continueWatching", JSON.stringify(filtered));
|
||||
} catch (err) {
|
||||
console.error("Failed to save continueWatching:", err);
|
||||
}
|
||||
localStorage.setItem("continueWatching", JSON.stringify(continueWatching));
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [streamUrl, subtitles, intro, outro]);
|
||||
|
||||
return <div ref={artRef} className="w-full h-full"></div>;
|
||||
return <div ref={artRef} className="w-full h-full" />;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import getAnimeInfo from "@/src/utils/getAnimeInfo.utils";
|
||||
@@ -113,58 +114,91 @@ export const useWatch = (animeId, initialEpisodeId) => {
|
||||
useEffect(() => {
|
||||
if (!episodeId || !episodes || isServerFetchInProgress.current) return;
|
||||
|
||||
let mounted = true;
|
||||
const controller = new AbortController();
|
||||
isServerFetchInProgress.current = true;
|
||||
setServerLoading(true);
|
||||
|
||||
const fetchServers = async () => {
|
||||
isServerFetchInProgress.current = true;
|
||||
setServerLoading(true);
|
||||
try {
|
||||
const data = await getServers(animeId, episodeId);
|
||||
console.log(data);
|
||||
const data = await getServers(animeId, episodeId, { signal: controller.signal });
|
||||
if (!mounted) return;
|
||||
|
||||
const filteredServers = data?.filter(
|
||||
(server) =>
|
||||
server.serverName === "HD-1" ||
|
||||
server.serverName === "HD-2" ||
|
||||
server.serverName === "HD-3"
|
||||
);
|
||||
if (filteredServers.some((s) => s.type === "sub")) {
|
||||
filteredServers.push({
|
||||
type: "sub",
|
||||
data_id: "69696969",
|
||||
server_id: "41",
|
||||
serverName: "HD-4",
|
||||
});
|
||||
// server.serverName === "HD-3" ||
|
||||
server.serverName === "Vidstreaming" ||
|
||||
server.serverName === "Vidcloud" ||
|
||||
server.serverName === "DouVideo"
|
||||
) || [];
|
||||
|
||||
let serversList = [...filteredServers];
|
||||
|
||||
if (serversList.some((s) => s.type === "sub")) {
|
||||
if (!serversList.some((s) => s.serverName === "HD-4" && s.type === "sub")) {
|
||||
serversList.push({
|
||||
type: "sub",
|
||||
data_id: "69696968",
|
||||
server_id: "41",
|
||||
serverName: "HD-4",
|
||||
});
|
||||
}
|
||||
}
|
||||
if (filteredServers.some((s) => s.type === "dub")) {
|
||||
filteredServers.push({
|
||||
type: "dub",
|
||||
data_id: "96969696",
|
||||
server_id: "42",
|
||||
serverName: "HD-4",
|
||||
});
|
||||
|
||||
if (serversList.some((s) => s.type === "dub")) {
|
||||
if (!serversList.some((s) => s.serverName === "HD-4" && s.type === "dub")) {
|
||||
serversList.push({
|
||||
type: "dub",
|
||||
data_id: "96969696",
|
||||
server_id: "42",
|
||||
serverName: "HD-4",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const savedServerName = localStorage.getItem("server_name");
|
||||
const savedServerType = localStorage.getItem("server_type");
|
||||
const initialServer =
|
||||
filteredServers.find(s => s.serverName === savedServerName && s.type === savedServerType) ||
|
||||
filteredServers.find(s => s.serverName === savedServerName) ||
|
||||
filteredServers.find(s => s.type === savedServerType && ["HD-1", "HD-2", "HD-3", "HD-4"].includes(s.serverName)) ||
|
||||
filteredServers.find(s => s.serverName === "HD-2") ||
|
||||
filteredServers[0];
|
||||
|
||||
setServers(filteredServers);
|
||||
const initialServer =
|
||||
serversList.find(s => s.serverName === savedServerName && s.type === savedServerType) ||
|
||||
serversList.find(s => s.serverName === savedServerName) ||
|
||||
serversList.find(s => s.serverName === "HD-2") ||
|
||||
serversList.find(
|
||||
s =>
|
||||
s.type === savedServerType &&
|
||||
["HD-1", "HD-2", "HD-3", "HD-4", "Vidstreaming", "Vidcloud", "DouVideo"].includes(s.serverName)
|
||||
) ||
|
||||
serversList[0];
|
||||
|
||||
setServers(serversList);
|
||||
setActiveServerType(initialServer?.type);
|
||||
setActiveServerName(initialServer?.serverName);
|
||||
setActiveServerId(initialServer?.data_id);
|
||||
} catch (error) {
|
||||
console.error("Error fetching servers:", error);
|
||||
setError(error.message || "An error occurred.");
|
||||
} catch (err) {
|
||||
if (err?.name === "AbortError") return;
|
||||
console.error("Error fetching servers:", err);
|
||||
if (mounted) setError(err.message || "An error occurred.");
|
||||
} finally {
|
||||
setServerLoading(false);
|
||||
isServerFetchInProgress.current = false;
|
||||
if (mounted) {
|
||||
setServerLoading(false);
|
||||
isServerFetchInProgress.current = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchServers();
|
||||
|
||||
return () => {
|
||||
mounted = false;
|
||||
try { controller.abort(); } catch (e) {
|
||||
// console.log(e.message);
|
||||
}
|
||||
isServerFetchInProgress.current = false;
|
||||
};
|
||||
}, [episodeId, episodes]);
|
||||
|
||||
// Fetch stream info only when episodeId, activeServerId, and servers are ready
|
||||
useEffect(() => {
|
||||
if (
|
||||
@@ -175,11 +209,10 @@ export const useWatch = (animeId, initialEpisodeId) => {
|
||||
isStreamFetchInProgress.current
|
||||
)
|
||||
return;
|
||||
if (
|
||||
(activeServerName?.toLowerCase() === "hd-1" || activeServerName?.toLowerCase() === "hd-4")
|
||||
&&
|
||||
!serverLoading
|
||||
) {
|
||||
const iframeServers = [];
|
||||
// const iframeServers = ["hd-1", "hd-4", "vidstreaming", "vidcloud", "douvideo"];
|
||||
|
||||
if (iframeServers.includes(activeServerName?.toLowerCase()) && !serverLoading) {
|
||||
setBuffering(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useLocation, useParams, Link, useNavigate } from "react-router-dom";
|
||||
import { useLanguage } from "@/src/context/LanguageContext";
|
||||
import { useWatch } from "@/src/hooks/useWatch";
|
||||
import BouncingLoader from "@/src/components/ui/bouncingloader/Bouncingloader";
|
||||
import IframePlayer from "@/src/components/player/IframePlayer";
|
||||
import Episodelist from "@/src/components/episodelist/Episodelist";
|
||||
import website_name from "@/src/config/website";
|
||||
import Sidecard from "@/src/components/sidecard/Sidecard";
|
||||
@@ -200,48 +199,45 @@ export default function Watch() {
|
||||
<div ref={playerRef} className="player w-full h-fit bg-black flex flex-col rounded-xl overflow-hidden shadow-2xl">
|
||||
<div ref={videoContainerRef} className="w-full relative aspect-video bg-black">
|
||||
{!buffering ? (
|
||||
["hd-1", "hd-4"].includes(activeServerName.toLowerCase()) ? (
|
||||
<IframePlayer
|
||||
episodeId={episodeId}
|
||||
servertype={activeServerType}
|
||||
serverName={activeServerName}
|
||||
animeInfo={animeInfo}
|
||||
episodeNum={activeEpisodeNum}
|
||||
episodes={episodes}
|
||||
playNext={setEpisodeId}
|
||||
autoNext={autoNext}
|
||||
/>
|
||||
) : (
|
||||
<Player
|
||||
streamUrl={streamUrl}
|
||||
subtitles={subtitles}
|
||||
intro={intro}
|
||||
outro={outro}
|
||||
serverName={activeServerName.toLowerCase()}
|
||||
thumbnail={thumbnail}
|
||||
autoSkipIntro={autoSkipIntro}
|
||||
autoPlay={autoPlay}
|
||||
autoNext={autoNext}
|
||||
episodeId={episodeId}
|
||||
episodes={episodes}
|
||||
playNext={setEpisodeId}
|
||||
animeInfo={animeInfo}
|
||||
episodeNum={activeEpisodeNum}
|
||||
streamInfo={streamInfo}
|
||||
/>
|
||||
)
|
||||
<Player
|
||||
streamUrl={streamUrl}
|
||||
subtitles={subtitles}
|
||||
intro={intro}
|
||||
outro={outro}
|
||||
activeServerName={activeServerName}
|
||||
thumbnail={thumbnail}
|
||||
autoSkipIntro={autoSkipIntro}
|
||||
autoPlay={autoPlay}
|
||||
autoNext={autoNext}
|
||||
episodeId={episodeId}
|
||||
episodes={episodes}
|
||||
playNext={setEpisodeId}
|
||||
animeInfo={animeInfo}
|
||||
episodeNum={activeEpisodeNum}
|
||||
streamInfo={streamInfo}
|
||||
/>
|
||||
) : (
|
||||
<div className="absolute inset-0 flex justify-center items-center bg-black">
|
||||
<div className="absolute inset-0 flex justify-center items-center bg-black bg-opacity-50">
|
||||
<BouncingLoader />
|
||||
</div>
|
||||
)}
|
||||
{!buffering && !activeServerType && (
|
||||
<div className="absolute inset-0 flex items-center justify-center bg-black/50 backdrop-blur-sm pointer-events-none">
|
||||
<p className="text-center text-gray-300 font-medium p-4 max-w-sm">
|
||||
Streaming server seems to be down. Please try another server or reload the page.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<p className="text-center underline font-medium text-[15px] absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 pointer-events-none">
|
||||
{!buffering && !streamInfo ? (
|
||||
servers ? (
|
||||
<>
|
||||
Probably this server is down, try other servers
|
||||
<br />
|
||||
Either reload or try again after sometime
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
Probably streaming server is down
|
||||
<br />
|
||||
Either reload or try again after sometime
|
||||
</>
|
||||
)
|
||||
) : null}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-[#121212]">
|
||||
|
||||
14
src/utils/title.utils.js
Normal file
14
src/utils/title.utils.js
Normal file
@@ -0,0 +1,14 @@
|
||||
export const getTitle = (item, language) => {
|
||||
if (!item) return "N/A";
|
||||
|
||||
const title = item.title;
|
||||
const japanese_title = item.japanese_title || item.japaneseTitle;
|
||||
|
||||
if (language === "EN") {
|
||||
if (typeof title === "string") return title;
|
||||
return title?.english || title?.romaji || "N/A";
|
||||
} else {
|
||||
// JP
|
||||
return japanese_title || (typeof title === "string" ? title : title?.romaji || title?.english || "N/A");
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user