diff --git a/src/components/InputBox.css b/src/components/InputBox.css
index d96ddf08..f1480b9c 100644
--- a/src/components/InputBox.css
+++ b/src/components/InputBox.css
@@ -19,7 +19,6 @@
.inputTextBox {
border-width: 0;
outline: none;
-
background-color: #36363e;
color: white;
padding: .7rem 1.5rem;
@@ -35,10 +34,36 @@
padding: .5rem 2.1rem;
font-weight: bold;
-
cursor: pointer;
}
+.inputDropdown {
+ border-width: 0;
+ outline: none;
+ background-color: #36363e;
+ color: white;
+ padding: .7rem 1rem;
+ height: auto;
+ width: 25%;
+ color: white;
+ font-weight: bold;
+ cursor: pointer;
+}
+
+.inputOptionBox {
+ border-width: 0;
+ outline: none;
+ background-color: #36363e;
+ color: white;
+ height: auto;
+ width: 10%;
+ box-sizing: border-box;
+}
+
+.inputDropdown:hover {
+ background-color: #3C3D44;
+}
+
.inputSearchButton:hover {
background-color: #9C3179;
}
@@ -47,6 +72,10 @@
background-color: #3C3D44;
}
+.inputOptionBox:hover {
+ background-color: #3C3D44;
+}
+
.inputSearchButton .text > .arrow {
opacity: 0;
transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out;
@@ -85,9 +114,24 @@
.inputSearchButton {
margin-top: .5rem;
+ align-self: center;
}
.inputTextBox {
+ margin-top: .5rem;
width: 100%;
}
+
+ .inputDropdown {
+ width: 100%;
+ padding: .7rem 1.5rem;
+ }
+
+ .inputOptionBox {
+ margin-top: .5rem;
+ width: 50%;
+ /* align-items:stretch; */
+ align-self: center;
+ padding: .7rem 1.5rem;
+ }
}
diff --git a/src/components/InputBox.js b/src/components/InputBox.js
index 35e6c1a2..a42900b9 100644
--- a/src/components/InputBox.js
+++ b/src/components/InputBox.js
@@ -4,23 +4,52 @@ import './InputBox.css'
// props = { onSubmit: (str) => {}, placeholder: string}
export function InputBox({ onSubmit, placeholder }) {
- const [value, setValue] = React.useState("");
+ const [searchTerm, setSearchTerm] = React.useState("");
+ const [type, setType] = React.useState("movie");
+ const [season, setSeason] = React.useState("");
+ const [episode, setEpisode] = React.useState("");
+
+ const showContentType = type === "show" ? false : true;
return (
)
}
diff --git a/src/components/MovieRow.js b/src/components/MovieRow.js
index a3ae80bd..c304aa4d 100644
--- a/src/components/MovieRow.js
+++ b/src/components/MovieRow.js
@@ -12,6 +12,7 @@ export function MovieRow(props) {
({props.year})
+
{props.season}x{props.episode}
Watch {props.type}
diff --git a/src/components/Title.css b/src/components/Title.css
index bd1790ed..6796dce9 100644
--- a/src/components/Title.css
+++ b/src/components/Title.css
@@ -1,7 +1,7 @@
.title {
font-size: 2rem;
color: white;
- max-width: 20rem;
+ /* max-width: 20rem; */
margin: 0;
padding: 0;
margin-bottom: 3.5rem;
diff --git a/src/lib/lookMovie.js b/src/lib/lookMovie.js
index 8acb5b00..914fe122 100644
--- a/src/lib/lookMovie.js
+++ b/src/lib/lookMovie.js
@@ -9,7 +9,13 @@ async function getVideoUrl(config) {
const accessToken = await getAccessToken(config);
const now = Math.floor(Date.now() / 1e3);
- let url = getCorsUrl(`https://lookmovie.io/manifests/movies/json/${config.movieId}/${now}/${accessToken}/master.m3u8`);
+ let url = '';
+
+ if (config.type === 'movie') {
+ url = getCorsUrl(`https://lookmovie.io/manifests/movies/json/${config.id}/${now}/${accessToken}/master.m3u8`);
+ } else if (config.type === 'show') {
+ url = getCorsUrl(`https://lookmovie.io/manifests/shows/json/${accessToken}/${now}/${config.id}/master.m3u8`);
+ }
if (url) {
const videoOpts = await fetch(url).then((d) => d.json());
@@ -31,7 +37,13 @@ async function getVideoUrl(config) {
}
async function getAccessToken(config) {
- let url = getCorsUrl(`https://lookmovie.io/api/v1/security/movie-access?id_movie=${config.movieId}&token=1&sk=&step=1`);
+ let url = '';
+
+ if (config.type === 'movie') {
+ url = getCorsUrl(`https://lookmovie.io/api/v1/security/movie-access?id_movie=${config.id}&token=1&sk=&step=1`);
+ } else if (config.type === 'show') {
+ url = getCorsUrl(`https://lookmovie.io/api/v1/security/show-access?slug=${config.slug}&token=&step=2`);
+ }
const data = await fetch(url).then((d) => d.json());
@@ -41,7 +53,7 @@ async function getAccessToken(config) {
return "Invalid type provided in config";
}
-async function getStreamUrl(slug, type) {
+async function getStreamUrl(slug, type, season, episode) {
const url = getCorsUrl(`https://lookmovie.io/${type}s/view/${slug}`);
const pageReq = await fetch(url).then((d) => d.text());
@@ -54,19 +66,35 @@ async function getStreamUrl(slug, type) {
"}"
);
+ let id = '';
+
+ if (type === "movie") {
+ id = data.id_movie;
+ } else if (type === "show") {
+ const episodeObj = data.seasons.find((v) => { return v.season === season && v.episode === episode; });
+
+ if (episodeObj) {
+ id = episodeObj.id_episode;
+ }
+ }
+
+ if (id === '') {
+ return { url: '' }
+ }
+
const videoUrl = await getVideoUrl({
slug: slug,
- movieId: data.id_movie,
+ id: id,
type: type,
});
return { url: videoUrl }
}
-async function findMovie(searchTerm) {
- const searchUrl = getCorsUrl(`https://lookmovie.io/api/v1/movies/search/?q=${encodeURIComponent(searchTerm)}`);
+async function findContent(searchTerm, type) {
+ const searchUrl = getCorsUrl(`https://lookmovie.io/api/v1/${type}s/search/?q=${encodeURIComponent(searchTerm)}`);
const searchRes = await fetch(searchUrl).then((d) => d.json());
- let results = [...searchRes.result.map((v) => ({ ...v, type: "movie" }))];
+ const results = [...searchRes.result.map((v) => ({ ...v, type: type}))];
const fuse = new Fuse(results, { threshold: 0.3, distance: 200, keys: ["title"] });
const matchedResults = fuse
@@ -97,4 +125,4 @@ async function findMovie(searchTerm) {
}
}
-export { findMovie, getStreamUrl };
\ No newline at end of file
+export { findContent, getStreamUrl };
\ No newline at end of file
diff --git a/src/serviceWorkerRegistration.js b/src/serviceWorkerRegistration.js
index 26468c7c..a96b00d5 100644
--- a/src/serviceWorkerRegistration.js
+++ b/src/serviceWorkerRegistration.js
@@ -55,10 +55,6 @@ function registerValidSW(swUrl, config) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
- console.log(
- 'New content is available and will be used when all ' +
- 'tabs for this page are closed. See https://cra.link/PWA.'
- );
// Execute callback
if (config && config.onUpdate) {
@@ -68,7 +64,6 @@ function registerValidSW(swUrl, config) {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
- console.log('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
@@ -108,7 +103,6 @@ function checkValidServiceWorker(swUrl, config) {
}
})
.catch(() => {
- console.log('No internet connection found. App is running in offline mode.');
});
}
diff --git a/src/views/Movie.js b/src/views/Movie.js
index d0f9a83e..a1b3438d 100644
--- a/src/views/Movie.js
+++ b/src/views/Movie.js
@@ -11,7 +11,7 @@ export function MovieView(props) {
- { streamData.title }
+ {streamData.title} {streamData.type === "show" ? `(${streamData.season}x${streamData.episode})` : '' }
diff --git a/src/views/Search.js b/src/views/Search.js
index 6ccafe3d..d40866e1 100644
--- a/src/views/Search.js
+++ b/src/views/Search.js
@@ -5,7 +5,7 @@ import { Card } from '../components/Card'
import { MovieRow } from '../components/MovieRow'
import { Arrow } from '../components/Arrow'
import { Progress } from '../components/Progress'
-import { findMovie, getStreamUrl } from '../lib/lookMovie'
+import { findContent, getStreamUrl } from '../lib/lookMovie'
import { useMovie } from '../hooks/useMovie';
import './Search.css'
@@ -26,17 +26,24 @@ export function SearchView() {
setFailed(true)
}
- async function getStream(title, slug, type) {
+ async function getStream(title, slug, type, season, episode) {
setStreamUrl("");
try {
setProgress(2);
setText(`Getting stream for "${title}"`)
- const { url } = await getStreamUrl(slug, type);
+ const { url } = await getStreamUrl(slug, type, season, episode);
+
+ if (url === '') {
+ return fail(`Not found: ${title} (${season}x${episode})`)
+ }
+
setProgress(maxSteps);
setStreamUrl(url);
setStreamData({
title,
type,
+ season,
+ episode
})
setText(`Streaming...`)
navigate("movie")
@@ -45,39 +52,44 @@ export function SearchView() {
}
}
- async function searchMovie(query) {
+ async function searchMovie(query, contentType, season, episode) {
setFailed(false);
- setText(`Searching for "${query}"`);
+ setText(`Searching for ${contentType} "${query}" ${contentType === 'show' ? ` (${season}x${episode})` : ''}`);
setProgress(1)
setShowingOptions(false)
try {
- const { options } = await findMovie(query)
+ const { options } = await findContent(query, contentType)
if (options.length === 0) {
- return fail("Could not find that movie")
+ return fail(`Could not find that ${contentType}`)
} else if (options.length > 1) {
+ options.forEach((o) => {
+ o.season = season;
+ o.episode = episode;
+ });
+
setProgress(2);
- setText("Choose your movie");
+ setText(`Choose your ${contentType}`);
setOptions(options);
setShowingOptions(true);
return;
}
const { title, slug, type } = options[0];
- getStream(title, slug, type);
+ getStream(title, slug, type, season, episode);
} catch (err) {
- fail("Failed to watch movie")
+ fail(`Failed to watch ${contentType}`)
}
}
return (
-
- What movie do you wanna watch?
+
+ What do you wanna watch?
- searchMovie(str)} />
+ searchMovie(str, type, season, episode)} />
@@ -86,9 +98,9 @@ export function SearchView() {
Whoops, there are a few movies like that
{options?.map((v, i) => (
-
{
+ {
setShowingOptions(false)
- getStream(v.title, v.slug, v.type)
+ getStream(v.title, v.slug, v.type, v.season, v.episode)
}}/>
))}