From 58d034e67bc18154725c70d57953e29d1c144649 Mon Sep 17 00:00:00 2001 From: femke77 Date: Wed, 16 Apr 2025 23:38:36 -0700 Subject: [PATCH 1/9] using server to proxy and sandbox videos --- README.md | 2 +- src/main.tsx | 22 + src/pages/watchPages/AdFreeTestMovie.tsx | 198 +++++++++ src/pages/watchPages/AdFreeTestTV.tsx | 521 +++++++++++++++++++++++ src/utils/data/servers.json | 5 + vite.config.ts | 3 +- 6 files changed, 749 insertions(+), 2 deletions(-) create mode 100644 src/pages/watchPages/AdFreeTestMovie.tsx create mode 100644 src/pages/watchPages/AdFreeTestTV.tsx diff --git a/README.md b/README.md index 091c40c..a1c8474 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Initial load 850-1000ms ### Metrics as of 4/14/2025 -- ~180-240 MB average browser memory usage after good amount of app usage with heavy caching strategies- holds steady. No leaking! +- Browser memory allocation is appropriate and doesn't increase over time with no activity. - Memory rises with video play normally, falls back to above numbers in under 2 min from watch page unmounting - ~42-72MB heap size depending on how much is cached by react query (depends on usage) - 99% performance by Lighthouse diff --git a/src/main.tsx b/src/main.tsx index 4ef47df..6bca6bd 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -20,6 +20,12 @@ import WatchPageSkeleton from './components/loadingSkeletons/WatchPageSkeleton.t import TextSkeleton from './components/loadingSkeletons/TextSkeleton.tsx'; import HistoryPageSkeleton from './components/loadingSkeletons/HistoryPageSkeleton.tsx'; +const AdFreeWatchTv = lazy( + () => import('./pages/watchPages/AdFreeTestTV.tsx'), +); +const MovieAdFree = lazy( + () => import('./pages/watchPages/AdFreeTestMovie.tsx'), +); const History = lazy(() => import('./pages/watchPages/History.tsx')); const CastMemberDetail = lazy( () => import('./pages/detailPages/CastMemberDetail.tsx'), @@ -194,6 +200,14 @@ const router = createBrowserRouter([ ), }, + { + path: 'movie/adfree/:movie_id', + element: ( + }> + + + ), + }, { path: 'tv/:series_id', element: ( @@ -202,6 +216,14 @@ const router = createBrowserRouter([ ), }, + { + path: 'tv/adfree/:series_id', + element: ( + }> + + + ), + }, ], }, { diff --git a/src/pages/watchPages/AdFreeTestMovie.tsx b/src/pages/watchPages/AdFreeTestMovie.tsx new file mode 100644 index 0000000..c2b0931 --- /dev/null +++ b/src/pages/watchPages/AdFreeTestMovie.tsx @@ -0,0 +1,198 @@ +import { useParams } from 'react-router-dom'; +import { useWatchDetails } from '../../hooks/useItemOrWatchDetail'; +import WatchDescription from '../../components/WatchDescription'; +import BackButton from '../../components/buttons/BackBtn'; +import FullscreenBtn from '../../components/buttons/FullScreenBtn'; +import ServerList from '../../components/lists/ServerList'; +import { isIphoneSafari, isIPad } from '../../utils/helpers'; +import serverData from '../../utils/data/servers.json'; +import { useEffect, useState, useRef } from 'react'; +import dayjs from 'dayjs'; +import useDocumentTitle from '../../hooks/usePageTitles'; +import { useStore } from '../../state/store'; + +const MovieAdFree = () => { + const { addToContinueWatchingMovie } = useStore(); + const { movie_id } = useParams<{ movie_id: string }>(); + const { data: movie } = useWatchDetails('movie', movie_id ?? ''); + const { servers } = serverData; + + const iframeRef = useRef(null); + const timeoutRef = useRef(null); + useDocumentTitle( + movie?.title + ? `Watch ${movie?.title || 'Movie'} | BingeBox` + : 'Loading... | BingeBox' + ); + + const [isLoading, setIsLoading] = useState(false); + const [selectedServer, setSelectedServer] = useState(() => { + const lastSelectedServer = localStorage.getItem('lastSelectedServer'); + return lastSelectedServer || servers[0].value; + }); + + + + useEffect(() => { + if (!movie) return; + // setTimeout(() => { + addToContinueWatchingMovie( + Number(movie_id), + 'movie', + dayjs().unix(), + movie.title, + movie.backdrop_path, + movie.release_date, + movie.runtime + ); + // }, 180000); + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [movie_id, movie]); + + useEffect(() => { + let newURL = ''; + switch (selectedServer) { + case 'vidsrc.xyz': + newURL = `/api/video/movie/${movie_id}`; + break; + case 'videasy.net': + newURL = `https://player.videasy.net/movie/${movie_id}`; + break; + case 'vidlink.pro': + newURL = `https://vidlink.pro/movie/${movie_id}`; + break; + case 'moviesapi.club': + newURL = `https://moviesapi.club/movie/${movie_id}`; + break; + case 'embed.su': + newURL = `https://embed.su/embed/movie/${movie_id}`; + break; + case 'nontongo.win': + newURL = `https://www.nontongo.win/embed/movie/${movie_id}`; + break; + case 'vidsrc.wtf': + newURL = `https://vidsrc.wtf/api/3/movie/?id=${movie_id}`; + break; + case 'vidsrc.wtf-ml': + newURL = `https://vidsrc.wtf/api/2/movie/?id=${movie_id}`; + break; + case '111movies.com': + newURL = ` https://111movies.com/movie/${movie_id}`; + break; + case 'vidfast.pro': + newURL = `https://vidfast.pro/movie/${movie_id}`; + break; + case 'superembed.stream': + newURL = ` https://multiembed.mov/directstream.php?video_id=${movie_id}&tmdb=1`; + break; + } + + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + setIsLoading(true); + if (iframeRef.current) { + iframeRef.current.contentWindow?.location.replace('about:blank'); + } + setTimeout(() => { + iframeRef.current?.contentWindow?.location.replace(newURL); + timeoutRef.current = setTimeout(() => { + setIsLoading(false); + }, 750); + }, 300); + + localStorage.setItem('lastSelectedServer', selectedServer); + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + timeoutRef.current = null; + } + }; + }, [selectedServer, movie_id]); + + return ( +
+
+
+
+
+ +
+ {movie && ( +

+ {movie.title || ''} +

+ )} + {/* iphone safari doesn't support the FS api */} +
+ +
+
+
+
+ + + {isLoading && ( +
+
+
+

+ Loading{' '} + { + servers.find( + (server) => server.value === selectedServer + )?.name + } + ...{' '} +

+
+
+ )} +
+ + {/* description */} +
+ {movie && ( + + )} +
+
+
+
+ {/* right side with server choices and episodes for tv*/} +
+ +
+
+
+
+ ); +}; + +export default MovieAdFree; diff --git a/src/pages/watchPages/AdFreeTestTV.tsx b/src/pages/watchPages/AdFreeTestTV.tsx new file mode 100644 index 0000000..dc0d1d5 --- /dev/null +++ b/src/pages/watchPages/AdFreeTestTV.tsx @@ -0,0 +1,521 @@ +import { useParams } from 'react-router-dom'; +import { + useWatchDetails, + useTVSeasonEpisodes, +} from '../../hooks/useItemOrWatchDetail'; +import WatchDescription from '../../components/WatchDescription'; +import BackButton from '../../components/buttons/BackBtn'; +import FullscreenBtn from '../../components/buttons/FullScreenBtn'; +import WatchPrevBtn from '../../components/buttons/WatchPrevBtn'; +import WatchNextBtn from '../../components/buttons/WatchNextBtn'; +import ListBoxComp from '../../components/selectors/ListBox'; +import serverData from '../../utils/data/servers.json'; +import { useEffect, useState, useRef } from 'react'; +import { Settings } from 'lucide-react'; +import SeasonNavigation from '../../components/buttons/SeasonNavigation'; +import { isIPad, isIphoneSafari } from '../../utils/helpers'; +import EpisodeList from '../../components/lists/EpisodeList'; +import dayjs from 'dayjs'; +import useDocumentTitle from '../../hooks/usePageTitles'; +import { useStore } from '../../state/store'; + +const AdFreeWatchTv = () => { + const VIEWING_PROGRESS_LIMIT = 250; + const { servers } = serverData; + const { addToContinueWatchingTv } = useStore(); + const iframeRef = useRef(null); + const timeoutRef = useRef(null); + const iframeLoadRef = useRef(null); + const { series_id } = useParams<{ series_id: string }>(); + const [isLoading, setIsLoading] = useState(true); + + const [selectedServer, setSelectedServer] = useState(() => { + const lastSelectedServer = localStorage.getItem('lastSelectedServer'); + return lastSelectedServer || servers[0].value; + }); + + const [viewProgress] = useState(() => { + const viewProgressObj = localStorage.getItem(`viewing-progress`); + if (viewProgressObj) { + const items = JSON.parse(viewProgressObj); + const progressItem = items[`tv-${series_id}`]; + if (progressItem) { + return { + [`tv-${series_id}`]: { + season: Number(progressItem.season), + episode: Number(progressItem.episode), + lastUpdated: Number(progressItem.lastUpdated), + }, + }; + } + return null; + } + return null; + }); + + const [selectedSeason, setSelectedSeason] = useState(() => { + if (viewProgress) { + const selectedSeason = viewProgress[`tv-${series_id}`]?.season; + if (selectedSeason) { + return Number(selectedSeason); + } + return 1; + } + return 1; + }); + + const [selectedEpisode, setSelectedEpisode] = useState(() => { + if (viewProgress) { + const selectedEpisode = viewProgress[`tv-${series_id}`]?.episode; + if (selectedEpisode) { + return Number(selectedEpisode); + } + return 1; + } + return 1; + }); + + const [currentSeasonLength, setCurrentSeasonLength] = useState(0); + const [previousSeasonLength, setPreviousSeasonLength] = useState(0); + + const prevServerRef = useRef(selectedServer); + + const { data: series } = useWatchDetails('tv', series_id!); + const { data: episodes } = useTVSeasonEpisodes( + series_id ?? '', + String(selectedSeason) + ); + useDocumentTitle( + series?.original_name + ? `Watch ${series?.original_name || 'TV Show'} | BingeBox` + : 'Loading... | BingeBox' + ); + const [unlocked, setUnlocked] = useState(false); + const interactionTimeoutRef = useRef(null); + + const handleMouseMove = (e: MouseEvent) => { + const el = document.elementFromPoint(e.clientX, e.clientY); + if (!el) return; + + const cursor = getComputedStyle(el).cursor; + // cursor is arrow when clickjack overlay is on + if (cursor === 'pointer' && !unlocked) { + console.log('Cursor is pointer. Unlocking iframe interaction.'); + + setUnlocked(true); + + if (interactionTimeoutRef.current) + clearTimeout(interactionTimeoutRef.current); + interactionTimeoutRef.current = setTimeout(() => { + setUnlocked(false); + console.log('Locking iframe interaction again.'); + }, 1000); //unlock for 1 second + } + }; + useEffect(() => { + window.addEventListener('mousemove', handleMouseMove); + + return () => { + window.removeEventListener('mousemove', handleMouseMove); + + if (interactionTimeoutRef.current) { + console.log('Clearing timeout...'); + clearTimeout(interactionTimeoutRef.current); + interactionTimeoutRef.current = null; + } + }; + }, []); + + useEffect(() => { + if (!series) return; + + // setTimeout(() => { + addToContinueWatchingTv( + Number(series_id!), + 'tv', + dayjs().unix(), + series.original_name, + selectedSeason, + selectedEpisode, + series.backdrop_path + ); + + // }, 180000); + // es-lint-disable-next-line react-hooks/exhaustive-deps + }, [series_id, series, selectedSeason, selectedEpisode]); + + useEffect(() => { + if (episodes) { + // Shift previous season length when moving to a new season + setPreviousSeasonLength(currentSeasonLength); + setCurrentSeasonLength(episodes?.episodes?.length); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedSeason, episodes]); + + useEffect(() => { + const updatedViewProgressItem = { + [`tv-${series_id}`]: { + season: selectedSeason, + episode: selectedEpisode, + lastUpdated: dayjs().unix(), + }, + }; + const viewProgressObj = localStorage.getItem(`viewing-progress`); + if (viewProgressObj) { + const viewProgress = JSON.parse(viewProgressObj); + // keep a rotation of 250 tv series in local storage and remove the oldest in favor of the most recent + if (Object.keys(viewProgress).length > VIEWING_PROGRESS_LIMIT) { + const oldestKey = Object.keys(viewProgress).reduce((oldest, key) => { + if (!viewProgress[oldest].lastUpdated) return key; + if (!viewProgress[key].lastUpdated) return oldest; + return viewProgress[key].lastUpdated < + viewProgress[oldest].lastUpdated + ? key + : oldest; + }, Object.keys(viewProgress)[0]); + delete viewProgress[oldestKey]; + } + const updatedViewProgress = { + ...viewProgress, + ...updatedViewProgressItem, + }; + + localStorage.setItem( + `viewing-progress`, + JSON.stringify(updatedViewProgress) + ); + } else { + localStorage.setItem( + `viewing-progress`, + JSON.stringify(updatedViewProgressItem) + ); + } + }, [series_id, selectedSeason, selectedEpisode]); + + // when page is remounted, user will see loading spinner for 750ms + useEffect(() => { + timeoutRef.current = setTimeout(() => { + setIsLoading(false); + }, 750); + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + timeoutRef.current = null; + } + }; + }, []); + + useEffect(() => { + let newURL = ''; + switch (selectedServer) { + case 'vidsrc.xyz': + newURL = `http://vidsrc.net/embed/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; + break; + case 'videasy.net': + newURL = `https://player.videasy.net/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; + break; + case 'vidlink.pro': + newURL = `https://vidlink.pro/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; + break; + case 'moviesapi.club': + newURL = `https://moviesapi.club/tv/${series_id}-${selectedSeason}-${selectedEpisode}`; + break; + case 'embed.su': + newURL = `https://embed.su/embed/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; + break; + case 'nontongo.win': + newURL = `https://www.nontongo.win/embed/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; + break; + case 'vidsrc.wtf': + newURL = `https://vidsrc.wtf/api/3/tv/?id=${series_id}&s=${selectedSeason}&e=${selectedEpisode}`; + break; + case 'vidsrc.wtf-ml': + newURL = `https://vidsrc.wtf/api/2/tv/?id=${series_id}&s=${selectedSeason}&e=${selectedEpisode}`; + break; + case '111movies.com': + newURL = `https://111movies.com/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; + break; + case 'vidfast.pro': + newURL = `https://vidfast.pro/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; + break; + case 'superembed.stream': + newURL = `https://multiembed.mov/directstream.php?video_id=${series_id}&tmdb=1&s=${selectedSeason}&e=${selectedEpisode}`; + break; + case 'vidsrc.xyz.adfree': + newURL = `/api/video/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; + break; + } + + const serverChanged = prevServerRef.current !== selectedServer; + prevServerRef.current = selectedServer; + + if (serverChanged) { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + + setIsLoading(true); + + if (iframeRef.current) { + iframeRef.current.contentWindow?.location.replace('about:blank'); + } + + iframeLoadRef.current = setTimeout(() => { + iframeRef.current?.contentWindow?.location.replace(newURL); + timeoutRef.current = setTimeout(() => { + setIsLoading(false); + }, 750); + }, 300); + + localStorage.setItem('lastSelectedServer', selectedServer); + } else { + iframeRef.current?.contentWindow?.location.replace(newURL); + } + + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + timeoutRef.current = null; + } + if (iframeLoadRef.current) { + clearTimeout(iframeLoadRef.current); + } + }; + }, [selectedServer, series_id, selectedSeason, selectedEpisode]); + + return ( +
+
+
+
+
+ +
+ {series && ( +

+ {series.original_name || ''} +

+ )} + +
+ +
+
+
+
+ {selectedServer === 'vidsrc.xyz.adfree' ? ( + + ) : ( + <> + {!unlocked && ( + // overlay that absorbs 'bad' clicks based on cursor state +
+ )} + + + )} + {isLoading && ( +
+
+
+

+ Loading{' '} + { + servers.find( + (server) => server.value === selectedServer + )?.name + } + ...{' '} +

+
+
+ )} +
+ {/* player controls (for tv) */} + {series && ( +
+
+
+
+
+ + Season {selectedSeason} • Episode{' '} + {selectedEpisode} + + {episodes ? ( + + {episodes?.episodes?.[selectedEpisode - 1]?.name} + + ) : ( + + Loading... + + )} +
+
+ {episodes ? ( +
+ + +
+ ) : ( +
+ + +
+ )} +
+
+
+
+ )} + +
+ {/* description */} + {series && ( + + )} +
+
+
+ {/* Sidebar */} +
+
+
+
+ {/* server selection */} + + +
+

Change Server

+

+ { + servers.find( + (server) => server.value === selectedServer + )?.name + } +

+
+
+ } + selectedOption={selectedServer} + setSelectedOption={setSelectedServer} + availableOptions={servers} + /> +
+
+ {/* season nav here */} + +
+
+
+ {/* episode list here */} + {episodes && ( + + )} +
+
+
+
+ + ); +}; + +export default AdFreeWatchTv; diff --git a/src/utils/data/servers.json b/src/utils/data/servers.json index bed60c9..3453d19 100644 --- a/src/utils/data/servers.json +++ b/src/utils/data/servers.json @@ -51,6 +51,11 @@ "id": 10, "name": "Server 10", "value": "superembed.stream" + }, + { + "id": 11, + "name": "Server 11 - Ad Free (Beta)", + "value": "vidsrc.xyz.adfree" } diff --git a/vite.config.ts b/vite.config.ts index c3c3b69..44c909c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -118,8 +118,9 @@ export default defineConfig({ host: true, proxy: { '/api': { - target: 'https://api.offlinetv.net', + target: 'http://localhost:3000', changeOrigin: true, + secure: false, }, }, }, From d7a87148a8669907de64ce5994e2aed0d49f497d Mon Sep 17 00:00:00 2001 From: femke77 Date: Sat, 10 May 2025 15:11:42 -0700 Subject: [PATCH 2/9] useSupense removed in hooks --- src/hooks/useItemOrWatchDetail.ts | 4 ++-- src/pages/watchPages/AdFreeTestMovie.tsx | 2 +- src/pages/watchPages/AdFreeTestTV.tsx | 2 +- src/utils/data/servers.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hooks/useItemOrWatchDetail.ts b/src/hooks/useItemOrWatchDetail.ts index c7e09a9..70f2312 100644 --- a/src/hooks/useItemOrWatchDetail.ts +++ b/src/hooks/useItemOrWatchDetail.ts @@ -120,7 +120,7 @@ export const useItemQuality = (id: string) => { // Watch Movie or Watch TV details including list of season 1 episodes. export const useWatchDetails = (type: string, id: string) => { - return useSuspenseQuery({ + return useQuery({ queryKey: ['watch-details', id, type], queryFn: async () => { if (!id) { @@ -159,7 +159,7 @@ export const useWatchDetails = (type: string, id: string) => { // get TV show episodes for a specific season export const useTVSeasonEpisodes = (id: string, season_num: string) => { - return useSuspenseQuery({ + return useQuery({ queryKey: ['tv-season-episodes', id, season_num], queryFn: async () => { if (!id || !season_num) { diff --git a/src/pages/watchPages/AdFreeTestMovie.tsx b/src/pages/watchPages/AdFreeTestMovie.tsx index c2b0931..3b88a7c 100644 --- a/src/pages/watchPages/AdFreeTestMovie.tsx +++ b/src/pages/watchPages/AdFreeTestMovie.tsx @@ -146,7 +146,7 @@ const MovieAdFree = () => { height='100%' src={`/api/video/movie/${movie_id}`} allow='encrypted-media' - sandbox='allow-scripts allow-same-origin allow-presentation' + sandbox='allow-scripts allow-same-origin' allowFullScreen > {isLoading && ( diff --git a/src/pages/watchPages/AdFreeTestTV.tsx b/src/pages/watchPages/AdFreeTestTV.tsx index dc0d1d5..678705c 100644 --- a/src/pages/watchPages/AdFreeTestTV.tsx +++ b/src/pages/watchPages/AdFreeTestTV.tsx @@ -319,7 +319,7 @@ const AdFreeWatchTv = () => { className='absolute top-0 left-0 w-full h-full bg-black' width='100%' height='100%' - sandbox='allow-scripts allow-same-origin allow-presentation' + sandbox='allow-scripts allow-same-origin' allow='encrypted-media; autoplay;' src={'about:blank'} allowFullScreen diff --git a/src/utils/data/servers.json b/src/utils/data/servers.json index 3453d19..70bd468 100644 --- a/src/utils/data/servers.json +++ b/src/utils/data/servers.json @@ -54,7 +54,7 @@ }, { "id": 11, - "name": "Server 11 - Ad Free (Beta)", + "name": "Ad Free (Beta) with Incognito", "value": "vidsrc.xyz.adfree" } From 53368c2366558af84439c4d0a481b0a5557cabf7 Mon Sep 17 00:00:00 2001 From: femke77 Date: Tue, 13 May 2025 14:58:48 -0700 Subject: [PATCH 3/9] minor fix --- src/components/selectors/GenreSelector.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/selectors/GenreSelector.tsx b/src/components/selectors/GenreSelector.tsx index 17a3655..132cadb 100644 --- a/src/components/selectors/GenreSelector.tsx +++ b/src/components/selectors/GenreSelector.tsx @@ -76,7 +76,7 @@ const GenreSelector = ({
- {/* {!unlocked && ( - // overlay that absorbs 'bad' clicks based on cursor state -
- )} */} - + {selectedServer === 'vidsrc.xyz.safe' || + selectedServer === 'videasy.net.safe' ? ( + + ) : ( + <> + {/* {!unlocked && ( + // overlay that absorbs 'bad' clicks based on cursor state +
+ )} */} + + + )} {isLoading && (
@@ -214,7 +237,7 @@ const WatchMovie = () => { Loading{' '} { servers.find( - (server) => server.value === selectedServer, + (server) => server.value === selectedServer )?.name } ...{' '} diff --git a/src/pages/watchPages/WatchTV.tsx b/src/pages/watchPages/WatchTV.tsx index ac9fb4e..d7b773a 100644 --- a/src/pages/watchPages/WatchTV.tsx +++ b/src/pages/watchPages/WatchTV.tsx @@ -243,6 +243,12 @@ const WatchTV = () => { case 'superembed.stream': newURL = `https://multiembed.mov/directstream.php?video_id=${series_id}&tmdb=1&s=${selectedSeason}&e=${selectedEpisode}`; break; + case 'vidsrc.xyz.safe': + newURL = `/api/video/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; + break; + case 'videasy.net.safe': + newURL = `https://player.videasy.net/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; + break; } const serverChanged = prevServerRef.current !== selectedServer; @@ -314,23 +320,37 @@ const WatchTV = () => { id='video-player' className='relative pt-[56.25%] w-full overflow-hidden mb-[24px] rounded-lg bg-[#1f1f1f] min-h-[300px]' > - {/* {!unlocked && ( - // overlay that absorbs 'bad' clicks based on cursor state -
- )} */} - + {selectedServer === 'vidsrc.xyz.safe' || selectedServer === 'videasy.net.safe'? ( + + ) : ( + <> + {/* {!unlocked && ( + // overlay that absorbs 'bad' clicks based on cursor state +
+ )} */} + + + )} {isLoading && (
diff --git a/src/utils/data/servers.json b/src/utils/data/servers.json index f662430..0f3acb2 100644 --- a/src/utils/data/servers.json +++ b/src/utils/data/servers.json @@ -54,8 +54,13 @@ }, { "id": 11, - "name": "Ad-Free (Beta)", - "value": "vidsrc.xyz.adfree" + "name": "Safe Server 1", + "value": "vidsrc.xyz.safe" + }, + { + "id": 12, + "name": "Safe Server 2", + "value": "videasy.net.safe" } From be6ce3ff9e4c228aa1f4dceaa4cabeb27a733079 Mon Sep 17 00:00:00 2001 From: femke77 Date: Thu, 15 May 2025 18:45:20 -0700 Subject: [PATCH 8/9] safe server 1 pointed to heroku api --- src/pages/watchPages/WatchMovie.tsx | 2 +- src/pages/watchPages/WatchTV.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/watchPages/WatchMovie.tsx b/src/pages/watchPages/WatchMovie.tsx index 6e29b52..050c7b0 100644 --- a/src/pages/watchPages/WatchMovie.tsx +++ b/src/pages/watchPages/WatchMovie.tsx @@ -139,7 +139,7 @@ const WatchMovie = () => { newURL = ` https://multiembed.mov/directstream.php?video_id=${movie_id}&tmdb=1`; break; case 'vidsrc.xyz.safe': - newURL = `/api/video/movie/${movie_id}`; + newURL = `https://bingebox-server-54dc60d03f7d.herokuapp.com/api/video/movie/${movie_id}`; break; case 'videasy.net.safe': newURL = `https://player.videasy.net/movie/${movie_id}`; diff --git a/src/pages/watchPages/WatchTV.tsx b/src/pages/watchPages/WatchTV.tsx index d7b773a..5e8e844 100644 --- a/src/pages/watchPages/WatchTV.tsx +++ b/src/pages/watchPages/WatchTV.tsx @@ -244,7 +244,7 @@ const WatchTV = () => { newURL = `https://multiembed.mov/directstream.php?video_id=${series_id}&tmdb=1&s=${selectedSeason}&e=${selectedEpisode}`; break; case 'vidsrc.xyz.safe': - newURL = `/api/video/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; + newURL = `https://bingebox-server-54dc60d03f7d.herokuapp.com/api/video/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; break; case 'videasy.net.safe': newURL = `https://player.videasy.net/tv/${series_id}/${selectedSeason}/${selectedEpisode}`; From 58811a3e556939dfc8a6a971ba7544b78dffecaa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 16 May 2025 01:48:17 +0000 Subject: [PATCH 9/9] chore: Auto-fix linting issues --- src/main.tsx | 3 +-- src/pages/FAQ.tsx | 3 ++- src/pages/watchPages/AdFreeTestMovie.tsx | 11 ++++------- src/pages/watchPages/AdFreeTestTV.tsx | 16 ++++++++-------- src/pages/watchPages/WatchMovie.tsx | 6 +++--- src/pages/watchPages/WatchTV.tsx | 5 +++-- 6 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/main.tsx b/src/main.tsx index 3fe6051..77c2843 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -216,7 +216,7 @@ const router = createBrowserRouter([ ), }, - + { path: 'tv/:series_id', element: ( @@ -225,7 +225,6 @@ const router = createBrowserRouter([ ), }, - ], }, { diff --git a/src/pages/FAQ.tsx b/src/pages/FAQ.tsx index 98d2c48..0d51051 100644 --- a/src/pages/FAQ.tsx +++ b/src/pages/FAQ.tsx @@ -38,7 +38,8 @@ const FAQPage = () => { const faqData = [ { question: 'Do I have to pay anything to use your site?', - answer: 'BingeBox is 100% free. We may start accepting donations in the future, strictly for your appreciation of the site, not the content.', + answer: + 'BingeBox is 100% free. We may start accepting donations in the future, strictly for your appreciation of the site, not the content.', }, { question: 'What about all these popups & redirects?', diff --git a/src/pages/watchPages/AdFreeTestMovie.tsx b/src/pages/watchPages/AdFreeTestMovie.tsx index 2f8cefa..db1f2c1 100644 --- a/src/pages/watchPages/AdFreeTestMovie.tsx +++ b/src/pages/watchPages/AdFreeTestMovie.tsx @@ -22,7 +22,7 @@ const MovieAdFree = () => { useDocumentTitle( movie?.title ? `Watch ${movie?.title || 'Movie'} | BingeBox` - : 'Loading... | BingeBox' + : 'Loading... | BingeBox', ); const [isLoading, setIsLoading] = useState(false); @@ -31,8 +31,6 @@ const MovieAdFree = () => { return lastSelectedServer || servers[0].value; }); - - useEffect(() => { if (!movie) return; // setTimeout(() => { @@ -43,7 +41,7 @@ const MovieAdFree = () => { movie.title, movie.backdrop_path, movie.release_date, - movie.runtime + movie.runtime, ); // }, 180000); @@ -137,7 +135,6 @@ const MovieAdFree = () => {
-