mirror of
https://github.com/movie-web/movie-web.git
synced 2025-09-13 18:13:24 +00:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
91757c0cda | ||
|
6acb51e8a3 | ||
|
fe0d2c91a4 | ||
|
e1b9393584 | ||
|
2d9bc0149f | ||
|
9bd5f30f40 | ||
|
0a15bb2023 | ||
|
cfa3cfd072 | ||
|
5fbe5d1ff5 | ||
|
4712d8fc5d | ||
|
a9d80ddf24 |
@@ -2,7 +2,7 @@ FROM node:20-alpine as build
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ENV PNPM_HOME="/pnpm"
|
ENV PNPM_HOME="/pnpm"
|
||||||
ENV PATH="$PNPM_HOME:$PATH"
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
RUN corepack enable
|
RUN npm i -g pnpm@8
|
||||||
|
|
||||||
COPY package.json ./
|
COPY package.json ./
|
||||||
COPY pnpm-lock.yaml ./
|
COPY pnpm-lock.yaml ./
|
||||||
|
112
package.json
112
package.json
@@ -3,6 +3,10 @@
|
|||||||
"version": "4.7.0",
|
"version": "4.7.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"homepage": "https://github.com/movie-web/movie-web",
|
"homepage": "https://github.com/movie-web/movie-web",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 20",
|
||||||
|
"pnpm": "^8"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
@@ -26,106 +30,106 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formkit/auto-animate": "^0.8.1",
|
"@formkit/auto-animate": "^0.8.2",
|
||||||
"@headlessui/react": "^1.7.17",
|
"@headlessui/react": "^1.7.19",
|
||||||
"@ladjs/country-language": "^1.0.3",
|
"@ladjs/country-language": "^1.0.3",
|
||||||
"@movie-web/providers": "^2.3.0",
|
"@movie-web/providers": "^2.3.0",
|
||||||
"@noble/hashes": "^1.3.3",
|
"@noble/hashes": "^1.4.0",
|
||||||
"@plasmohq/messaging": "^0.6.1",
|
"@plasmohq/messaging": "^0.6.2",
|
||||||
"@react-spring/web": "^9.7.3",
|
"@react-spring/web": "^9.7.3",
|
||||||
"@scure/bip39": "^1.2.2",
|
"@scure/bip39": "^1.3.0",
|
||||||
"@sozialhelden/ietf-language-tags": "^5.4.2",
|
"@sozialhelden/ietf-language-tags": "^5.4.2",
|
||||||
"@types/node-forge": "^1.3.10",
|
"@types/node-forge": "^1.3.11",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.5.1",
|
||||||
"core-js": "^3.34.0",
|
"core-js": "^3.37.0",
|
||||||
"detect-browser": "^5.3.0",
|
"detect-browser": "^5.3.0",
|
||||||
"dompurify": "^3.0.6",
|
"dompurify": "^3.1.0",
|
||||||
"flag-icons": "^7.1.0",
|
"flag-icons": "^7.2.1",
|
||||||
"focus-trap-react": "^10.2.3",
|
"focus-trap-react": "^10.2.3",
|
||||||
"fscreen": "^1.2.0",
|
"fscreen": "^1.2.0",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
"hls.js": "^1.5.7",
|
"hls.js": "^1.5.8",
|
||||||
"i18next": "^23.7.11",
|
"i18next": "^23.11.2",
|
||||||
"immer": "^10.0.3",
|
"immer": "^10.0.4",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"lodash.isequal": "^4.5.0",
|
"lodash.isequal": "^4.5.0",
|
||||||
"lodash.merge": "^4.6.2",
|
"lodash.merge": "^4.6.2",
|
||||||
"million": "^2.6.4",
|
"million": "^3.0.6",
|
||||||
"nanoid": "^5.0.4",
|
"nanoid": "^5.0.7",
|
||||||
"node-forge": "^1.3.1",
|
"node-forge": "^1.3.1",
|
||||||
"ofetch": "^1.3.3",
|
"ofetch": "^1.3.4",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-ga4": "^2.1.0",
|
"react-ga4": "^2.1.0",
|
||||||
"react-google-recaptcha-v3": "^1.10.1",
|
"react-google-recaptcha-v3": "^1.10.1",
|
||||||
"react-helmet-async": "^2.0.4",
|
"react-helmet-async": "^2.0.4",
|
||||||
"react-i18next": "^14.0.0",
|
"react-i18next": "^14.1.0",
|
||||||
"react-lazy-with-preload": "^2.2.1",
|
"react-lazy-with-preload": "^2.2.1",
|
||||||
"react-router-dom": "^6.21.1",
|
"react-router-dom": "^6.22.3",
|
||||||
"react-sticky-el": "^2.1.0",
|
"react-sticky-el": "^2.1.0",
|
||||||
"react-turnstile": "^1.1.2",
|
"react-turnstile": "^1.1.3",
|
||||||
"react-use": "^17.4.2",
|
"react-use": "^17.5.0",
|
||||||
"semver": "^7.5.4",
|
"semver": "^7.6.0",
|
||||||
"slugify": "^1.6.6",
|
"slugify": "^1.6.6",
|
||||||
"subsrt-ts": "^2.1.2",
|
"subsrt-ts": "^2.1.2",
|
||||||
"zustand": "^4.4.7"
|
"zustand": "^4.5.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.23.6",
|
"@babel/core": "^7.24.4",
|
||||||
"@babel/preset-env": "^7.23.6",
|
"@babel/preset-env": "^7.24.4",
|
||||||
"@babel/preset-typescript": "^7.23.3",
|
"@babel/preset-typescript": "^7.24.1",
|
||||||
"@rollup/wasm-node": "^4.9.4",
|
"@rollup/wasm-node": "^4.15.0",
|
||||||
"@types/chromecast-caf-sender": "^1.0.8",
|
"@types/chromecast-caf-sender": "^1.0.9",
|
||||||
"@types/crypto-js": "^4.2.1",
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/dompurify": "^3.0.5",
|
"@types/dompurify": "^3.0.5",
|
||||||
"@types/fscreen": "^1.0.4",
|
"@types/fscreen": "^1.0.4",
|
||||||
"@types/lodash.isequal": "^4.5.8",
|
"@types/lodash.isequal": "^4.5.8",
|
||||||
"@types/lodash.merge": "^4.6.9",
|
"@types/lodash.merge": "^4.6.9",
|
||||||
"@types/lodash.throttle": "^4.1.9",
|
"@types/lodash.throttle": "^4.1.9",
|
||||||
"@types/node": "^20.10.5",
|
"@types/node": "^20.12.7",
|
||||||
"@types/pako": "^2.0.3",
|
"@types/pako": "^2.0.3",
|
||||||
"@types/react": "^18.2.45",
|
"@types/react": "^18.2.79",
|
||||||
"@types/react-dom": "^18.2.18",
|
"@types/react-dom": "^18.2.25",
|
||||||
"@types/react-helmet": "^6.1.11",
|
"@types/react-helmet": "^6.1.11",
|
||||||
"@types/react-router": "^5.1.20",
|
"@types/react-router": "^5.1.20",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@types/react-stickynode": "^4.0.3",
|
"@types/react-stickynode": "^4.0.3",
|
||||||
"@types/react-transition-group": "^4.4.10",
|
"@types/react-transition-group": "^4.4.10",
|
||||||
"@types/semver": "^7.5.6",
|
"@types/semver": "^7.5.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.15.0",
|
"@typescript-eslint/eslint-plugin": "^7.7.0",
|
||||||
"@typescript-eslint/parser": "^6.15.0",
|
"@typescript-eslint/parser": "^7.7.0",
|
||||||
"@vitejs/plugin-react": "^4.2.1",
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
"autoprefixer": "^10.4.16",
|
"autoprefixer": "^10.4.19",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-airbnb": "19.0.4",
|
"eslint-config-airbnb": "19.0.4",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-import-resolver-typescript": "^3.6.1",
|
"eslint-import-resolver-typescript": "^3.6.1",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||||
"eslint-plugin-prettier": "^5.1.1",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-react": "7.33.2",
|
"eslint-plugin-react": "7.34.1",
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "4.6.0",
|
||||||
"glob": "^10.3.10",
|
"glob": "^10.3.12",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
"jsdom": "^23.0.1",
|
"jsdom": "^24.0.0",
|
||||||
"postcss": "^8.4.32",
|
"postcss": "^8.4.38",
|
||||||
"postcss-rtl": "^2.0.0",
|
"postcss-rtl": "^2.0.0",
|
||||||
"postcss-rtlcss": "^4.0.9",
|
"postcss-rtlcss": "^5.1.2",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.2.5",
|
||||||
"prettier-plugin-tailwindcss": "^0.5.9",
|
"prettier-plugin-tailwindcss": "^0.5.14",
|
||||||
"rollup-plugin-visualizer": "^5.11.0",
|
"rollup-plugin-visualizer": "^5.12.0",
|
||||||
"tailwind-scrollbar": "^3.0.5",
|
"tailwind-scrollbar": "^3.1.0",
|
||||||
"tailwindcss": "^3.4.0",
|
"tailwindcss": "^3.4.3",
|
||||||
"tailwindcss-themer": "^4.0.0",
|
"tailwindcss-themer": "^4.0.0",
|
||||||
"type-fest": "^4.8.3",
|
"type-fest": "^4.15.0",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.4.5",
|
||||||
"vite": "^5.0.13",
|
"vite": "^5.2.9",
|
||||||
"vite-plugin-checker": "^0.6.2",
|
"vite-plugin-checker": "^0.6.4",
|
||||||
"vite-plugin-package-version": "^1.1.0",
|
"vite-plugin-package-version": "^1.1.0",
|
||||||
"vite-plugin-pwa": "^0.17.4",
|
"vite-plugin-pwa": "^0.19.8",
|
||||||
"vite-plugin-static-copy": "^1.0.0",
|
"vite-plugin-static-copy": "^1.0.3",
|
||||||
"vitest": "^1.1.0",
|
"vitest": "^1.5.0",
|
||||||
"workbox-window": "^7.0.0"
|
"workbox-window": "^7.0.0"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
3537
pnpm-lock.yaml
generated
3537
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -135,13 +135,15 @@ export async function getLegacyMetaFromId(
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
let imdbId = data.external_ids.find((v) => v.provider === "imdb_latest")
|
let imdbId = data.external_ids.find(
|
||||||
?.external_id;
|
(v) => v.provider === "imdb_latest",
|
||||||
|
)?.external_id;
|
||||||
if (!imdbId)
|
if (!imdbId)
|
||||||
imdbId = data.external_ids.find((v) => v.provider === "imdb")?.external_id;
|
imdbId = data.external_ids.find((v) => v.provider === "imdb")?.external_id;
|
||||||
|
|
||||||
let tmdbId = data.external_ids.find((v) => v.provider === "tmdb_latest")
|
let tmdbId = data.external_ids.find(
|
||||||
?.external_id;
|
(v) => v.provider === "tmdb_latest",
|
||||||
|
)?.external_id;
|
||||||
if (!tmdbId)
|
if (!tmdbId)
|
||||||
tmdbId = data.external_ids.find((v) => v.provider === "tmdb")?.external_id;
|
tmdbId = data.external_ids.find((v) => v.provider === "tmdb")?.external_id;
|
||||||
|
|
||||||
|
@@ -153,6 +153,12 @@ const tmdbHeaders = {
|
|||||||
Authorization: `Bearer ${apiKey}`,
|
Authorization: `Bearer ${apiKey}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function abortOnTimeout(timeout: number): AbortSignal {
|
||||||
|
const controller = new AbortController();
|
||||||
|
setTimeout(() => controller.abort(), timeout);
|
||||||
|
return controller.signal;
|
||||||
|
}
|
||||||
|
|
||||||
async function get<T>(url: string, params?: object): Promise<T> {
|
async function get<T>(url: string, params?: object): Promise<T> {
|
||||||
if (!apiKey) throw new Error("TMDB API key not set");
|
if (!apiKey) throw new Error("TMDB API key not set");
|
||||||
try {
|
try {
|
||||||
@@ -162,7 +168,7 @@ async function get<T>(url: string, params?: object): Promise<T> {
|
|||||||
params: {
|
params: {
|
||||||
...params,
|
...params,
|
||||||
},
|
},
|
||||||
signal: AbortSignal.timeout(5000),
|
signal: abortOnTimeout(5000),
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return mwFetch<T>(encodeURI(url), {
|
return mwFetch<T>(encodeURI(url), {
|
||||||
@@ -171,7 +177,7 @@ async function get<T>(url: string, params?: object): Promise<T> {
|
|||||||
params: {
|
params: {
|
||||||
...params,
|
...params,
|
||||||
},
|
},
|
||||||
signal: AbortSignal.timeout(30000),
|
signal: abortOnTimeout(30000),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -46,10 +46,14 @@ function Button(props: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function useSeasons(mediaId: string, isLastEpisode: boolean = false) {
|
function useSeasons(
|
||||||
|
mediaId: string | undefined,
|
||||||
|
isLastEpisode: boolean = false,
|
||||||
|
) {
|
||||||
const state = useAsync(async () => {
|
const state = useAsync(async () => {
|
||||||
if (isLastEpisode) {
|
if (isLastEpisode) {
|
||||||
const data = await getMetaFromId(MWMediaType.SERIES, mediaId ?? "");
|
if (!mediaId) return null;
|
||||||
|
const data = await getMetaFromId(MWMediaType.SERIES, mediaId);
|
||||||
if (data?.meta.type !== MWMediaType.SERIES) return null;
|
if (data?.meta.type !== MWMediaType.SERIES) return null;
|
||||||
return data.meta.seasons;
|
return data.meta.seasons;
|
||||||
}
|
}
|
||||||
@@ -60,13 +64,14 @@ function useSeasons(mediaId: string, isLastEpisode: boolean = false) {
|
|||||||
|
|
||||||
function useNextSeasonEpisode(
|
function useNextSeasonEpisode(
|
||||||
nextSeason: MWSeasonMeta | undefined,
|
nextSeason: MWSeasonMeta | undefined,
|
||||||
mediaId: string,
|
mediaId: string | undefined,
|
||||||
) {
|
) {
|
||||||
const state = useAsync(async () => {
|
const state = useAsync(async () => {
|
||||||
if (nextSeason) {
|
if (nextSeason) {
|
||||||
|
if (!mediaId) return null;
|
||||||
const data = await getMetaFromId(
|
const data = await getMetaFromId(
|
||||||
MWMediaType.SERIES,
|
MWMediaType.SERIES,
|
||||||
mediaId ?? "",
|
mediaId,
|
||||||
nextSeason?.id,
|
nextSeason?.id,
|
||||||
);
|
);
|
||||||
if (data?.meta.type !== MWMediaType.SERIES) return null;
|
if (data?.meta.type !== MWMediaType.SERIES) return null;
|
||||||
@@ -106,18 +111,17 @@ export function NextEpisodeButton(props: {
|
|||||||
const enableAutoplay = usePreferencesStore((s) => s.enableAutoplay);
|
const enableAutoplay = usePreferencesStore((s) => s.enableAutoplay);
|
||||||
|
|
||||||
const isLastEpisode =
|
const isLastEpisode =
|
||||||
meta?.episode?.number === meta?.episodes?.at(-1)?.number;
|
!meta?.episode?.number || !meta?.episodes?.at(-1)?.number
|
||||||
|
? false
|
||||||
|
: meta.episode.number === meta.episodes.at(-1)!.number;
|
||||||
|
|
||||||
const seasons = useSeasons(meta?.tmdbId ?? "", isLastEpisode);
|
const seasons = useSeasons(meta?.tmdbId, isLastEpisode);
|
||||||
|
|
||||||
const nextSeason = seasons.value?.find(
|
const nextSeason = seasons.value?.find(
|
||||||
(season) => season.number === (meta?.season?.number ?? 0) + 1,
|
(season) => season.number === (meta?.season?.number ?? 0) + 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
const nextSeasonEpisode = useNextSeasonEpisode(
|
const nextSeasonEpisode = useNextSeasonEpisode(nextSeason, meta?.tmdbId);
|
||||||
nextSeason,
|
|
||||||
meta?.tmdbId ?? "",
|
|
||||||
);
|
|
||||||
|
|
||||||
let show = false;
|
let show = false;
|
||||||
const hasAutoplayed = useRef(false);
|
const hasAutoplayed = useRef(false);
|
||||||
|
Reference in New Issue
Block a user