From a1f3986e6434f4ac04bc7c1df7bc9cca8d049442 Mon Sep 17 00:00:00 2001 From: zisra <100528712+zisra@users.noreply.github.com> Date: Mon, 27 Feb 2023 00:58:36 -0600 Subject: [PATCH 01/27] Picture in picture --- src/components/Icon.tsx | 2 + src/setup/locales/en/translation.json | 3 +- src/utils/detectFeatures.ts | 4 ++ src/video/components/VideoPlayer.tsx | 3 ++ .../components/actions/DownloadAction.tsx | 2 +- .../actions/PictureInPictureAction.tsx | 38 +++++++++++++++++++ src/video/state/init.ts | 1 + src/video/state/logic/controls.ts | 5 +++ .../state/providers/castingStateProvider.ts | 4 ++ src/video/state/providers/providerTypes.ts | 1 + .../state/providers/videoStateProvider.ts | 15 ++++++++ src/video/state/types.ts | 1 + 12 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 src/video/components/actions/PictureInPictureAction.tsx diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index ff1cef8c..382b7133 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -36,6 +36,7 @@ export enum Icons { CASTING = "casting", CIRCLE_EXCLAMATION = "circle_exclamation", DOWNLOAD = "download", + PICTURE_IN_PICTURE = "pictureInPicture", } export interface IconProps { @@ -79,6 +80,7 @@ const iconList: Record = { circle_exclamation: ``, casting: "", download: ``, + pictureInPicture: ``, }; function ChromeCastButton() { diff --git a/src/setup/locales/en/translation.json b/src/setup/locales/en/translation.json index 5a3fe230..f358f841 100644 --- a/src/setup/locales/en/translation.json +++ b/src/setup/locales/en/translation.json @@ -61,7 +61,8 @@ "episodes": "Episodes", "source": "Source", "captions": "Captions", - "download": "Download" + "download": "Download", + "pictureInPicture": "Picture in Picture" }, "popouts": { "sources": "Sources", diff --git a/src/utils/detectFeatures.ts b/src/utils/detectFeatures.ts index 15be4c69..0180ae49 100644 --- a/src/utils/detectFeatures.ts +++ b/src/utils/detectFeatures.ts @@ -38,3 +38,7 @@ export function canWebkitFullscreen(): boolean { export function canFullscreen(): boolean { return canFullscreenAnyElement() || canWebkitFullscreen(); } + +export function canPictureInPicture(): boolean { + return "pictureInPictureEnabled" in document; +} diff --git a/src/video/components/VideoPlayer.tsx b/src/video/components/VideoPlayer.tsx index 9553b70c..7aef90bc 100644 --- a/src/video/components/VideoPlayer.tsx +++ b/src/video/components/VideoPlayer.tsx @@ -31,6 +31,7 @@ import { PopoutProviderAction } from "@/video/components/popouts/PopoutProviderA import { ChromecastAction } from "@/video/components/actions/ChromecastAction"; import { CastingTextAction } from "@/video/components/actions/CastingTextAction"; import { DownloadAction } from "@/video/components/actions/DownloadAction"; +import { PictureInPictureAction } from "@/video/components/actions/PictureInPictureAction"; type Props = VideoPlayerBaseProps; @@ -144,6 +145,7 @@ export function VideoPlayer(props: Props) {
+ @@ -161,6 +163,7 @@ export function VideoPlayer(props: Props) { + diff --git a/src/video/components/actions/DownloadAction.tsx b/src/video/components/actions/DownloadAction.tsx index 10d59ce5..307f14c7 100644 --- a/src/video/components/actions/DownloadAction.tsx +++ b/src/video/components/actions/DownloadAction.tsx @@ -28,7 +28,7 @@ export function DownloadAction(props: Props) { href={isHLS ? undefined : sourceInterface.source?.url} rel="noreferrer" target="_blank" - download={title ? normalizeTitle(title) : undefined} + download={title ? `${normalizeTitle(title)}.mp4` : undefined} > { + controls.togglePictureInPicture(); + }, [controls]); + + if (!canPictureInPicture()) return null; + + return ( + + ); +} diff --git a/src/video/state/init.ts b/src/video/state/init.ts index 13118a1d..6a67777d 100644 --- a/src/video/state/init.ts +++ b/src/video/state/init.ts @@ -31,6 +31,7 @@ function initPlayer(): VideoPlayerState { isFocused: false, leftControlHovering: false, popoutBounds: null, + isPictureInPicture: false, }, mediaPlaying: { diff --git a/src/video/state/logic/controls.ts b/src/video/state/logic/controls.ts index 56c89a10..f21ec05a 100644 --- a/src/video/state/logic/controls.ts +++ b/src/video/state/logic/controls.ts @@ -13,6 +13,7 @@ export type ControlMethods = { setMeta(data?: VideoPlayerMeta): void; setCurrentEpisode(sId: string, eId: string): void; setDraggingTime(num: number): void; + togglePictureInPicture(): void; }; export function useControls( @@ -100,5 +101,9 @@ export function useControls( updateMeta(descriptor, state); } }, + togglePictureInPicture() { + state.stateProvider?.togglePictureInPicture(); + updateInterface(descriptor, state); + }, }; } diff --git a/src/video/state/providers/castingStateProvider.ts b/src/video/state/providers/castingStateProvider.ts index e3b56dfb..520ca814 100644 --- a/src/video/state/providers/castingStateProvider.ts +++ b/src/video/state/providers/castingStateProvider.ts @@ -148,6 +148,10 @@ export function createCastingStateProvider( updateSource(descriptor, state); } }, + togglePictureInPicture() { + controller?.togglePictureInPicture(); + updateSource(descriptor, state); + }, providerStart() { this.setVolume(getStoredVolume()); diff --git a/src/video/state/providers/providerTypes.ts b/src/video/state/providers/providerTypes.ts index e34b950d..1643a980 100644 --- a/src/video/state/providers/providerTypes.ts +++ b/src/video/state/providers/providerTypes.ts @@ -19,6 +19,7 @@ export type VideoPlayerStateController = { setCaption(id: string, url: string): void; clearCaption(): void; getId(): string; + togglePictureInPicture(): void; }; export type VideoPlayerStateProvider = VideoPlayerStateController & { diff --git a/src/video/state/providers/videoStateProvider.ts b/src/video/state/providers/videoStateProvider.ts index ae009aae..729ac0b0 100644 --- a/src/video/state/providers/videoStateProvider.ts +++ b/src/video/state/providers/videoStateProvider.ts @@ -5,6 +5,7 @@ import { canFullscreen, canFullscreenAnyElement, canWebkitFullscreen, + canPictureInPicture, } from "@/utils/detectFeatures"; import { MWStreamType } from "@/backend/helpers/streams"; import { updateInterface } from "@/video/state/logic/interface"; @@ -204,6 +205,20 @@ export function createVideoStateProvider( updateSource(descriptor, state); } }, + async togglePictureInPicture() { + if (!canPictureInPicture()) return; + if (player !== document.pictureInPictureElement) { + try { + await player.requestPictureInPicture(); + } catch { + state.interface.isPictureInPicture = false; + } + state.interface.isPictureInPicture = true; + } else { + await document.exitPictureInPicture(); + state.interface.isPictureInPicture = false; + } + }, providerStart() { this.setVolume(getStoredVolume()); diff --git a/src/video/state/types.ts b/src/video/state/types.ts index 6b04a55a..b1557d7f 100644 --- a/src/video/state/types.ts +++ b/src/video/state/types.ts @@ -30,6 +30,7 @@ export type VideoPlayerState = { isFocused: boolean; // is the video player the users focus? (shortcuts only works when its focused) leftControlHovering: boolean; // is the cursor hovered over the left side of player controls popoutBounds: null | DOMRect; // bounding box of current popout + isPictureInPicture: boolean; // is picture in picture active }; // state related to the playing state of the media From b9026c50f533245121b83fe3d6e722934e82a924 Mon Sep 17 00:00:00 2001 From: zisra <100528712+zisra@users.noreply.github.com> Date: Mon, 27 Feb 2023 00:58:47 -0600 Subject: [PATCH 02/27] Picture in picture --- public/config.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/public/config.js b/public/config.js index eb936081..45c940b8 100644 --- a/public/config.js +++ b/public/config.js @@ -1,7 +1,6 @@ window.__CONFIG__ = { // url must NOT end with a slash - VITE_CORS_PROXY_URL: "", - + VITE_CORS_PROXY_URL: "https://cors.movie-web.app", VITE_TMDB_API_KEY: "b030404650f279792a8d3287232358e3", VITE_OMDB_API_KEY: "aa0937c0", }; From f2f7925cbb31e2a9d9edd1d99f7f445b9a0a151a Mon Sep 17 00:00:00 2001 From: zisra <100528712+zisra@users.noreply.github.com> Date: Mon, 27 Feb 2023 01:19:38 -0600 Subject: [PATCH 03/27] CSS changes --- public/config.js | 2 +- src/setup/index.css | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/public/config.js b/public/config.js index 45c940b8..b69f60eb 100644 --- a/public/config.js +++ b/public/config.js @@ -1,6 +1,6 @@ window.__CONFIG__ = { // url must NOT end with a slash - VITE_CORS_PROXY_URL: "https://cors.movie-web.app", + VITE_CORS_PROXY_URL: "", VITE_TMDB_API_KEY: "b030404650f279792a8d3287232358e3", VITE_OMDB_API_KEY: "aa0937c0", }; diff --git a/src/setup/index.css b/src/setup/index.css index c3d97c26..3e34eec3 100644 --- a/src/setup/index.css +++ b/src/setup/index.css @@ -4,12 +4,13 @@ html, body { - @apply bg-denim-100 text-denim-700 font-open-sans overflow-x-hidden; + @apply bg-denim-100 font-open-sans text-denim-700 overflow-x-hidden; min-height: 100vh; min-height: 100dvh; } -html[data-full], html[data-full] body { +html[data-full], +html[data-full] body { overscroll-behavior-y: none; } @@ -46,10 +47,15 @@ body[data-no-select] { overflow: hidden; display: -webkit-box; -webkit-line-clamp: 1; - -webkit-box-orient: vertical; + -webkit-box-orient: vertical; overflow: hidden; } .google-cast-button:not(.casting) google-cast-launcher { @apply brightness-[500]; } + +:picture-in-picture { + opacity: 0.3; + filter: blur(5px); +} From 3fad6edaadbe04ad8472196778bd48f166e37589 Mon Sep 17 00:00:00 2001 From: zisra <100528712+zisra@users.noreply.github.com> Date: Mon, 27 Feb 2023 03:43:14 -0600 Subject: [PATCH 04/27] Webkit support --- src/setup/index.css | 5 ---- src/utils/detectFeatures.ts | 4 +++ .../state/providers/videoStateProvider.ts | 30 ++++++++++++------- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/setup/index.css b/src/setup/index.css index 3e34eec3..ebb56bec 100644 --- a/src/setup/index.css +++ b/src/setup/index.css @@ -54,8 +54,3 @@ body[data-no-select] { .google-cast-button:not(.casting) google-cast-launcher { @apply brightness-[500]; } - -:picture-in-picture { - opacity: 0.3; - filter: blur(5px); -} diff --git a/src/utils/detectFeatures.ts b/src/utils/detectFeatures.ts index 0180ae49..af62720d 100644 --- a/src/utils/detectFeatures.ts +++ b/src/utils/detectFeatures.ts @@ -42,3 +42,7 @@ export function canFullscreen(): boolean { export function canPictureInPicture(): boolean { return "pictureInPictureEnabled" in document; } + +export function canWebkitPictureInPicture(): boolean { + return "webkitSupportsPresentationMode" in document.createElement("video"); +} diff --git a/src/video/state/providers/videoStateProvider.ts b/src/video/state/providers/videoStateProvider.ts index 729ac0b0..cd2aa6f2 100644 --- a/src/video/state/providers/videoStateProvider.ts +++ b/src/video/state/providers/videoStateProvider.ts @@ -6,6 +6,7 @@ import { canFullscreenAnyElement, canWebkitFullscreen, canPictureInPicture, + canWebkitPictureInPicture, } from "@/utils/detectFeatures"; import { MWStreamType } from "@/backend/helpers/streams"; import { updateInterface } from "@/video/state/logic/interface"; @@ -205,18 +206,27 @@ export function createVideoStateProvider( updateSource(descriptor, state); } }, - async togglePictureInPicture() { - if (!canPictureInPicture()) return; - if (player !== document.pictureInPictureElement) { - try { - await player.requestPictureInPicture(); - } catch { + togglePictureInPicture() { + if (canWebkitPictureInPicture()) { + const webkitPlayer = player as any; + webkitPlayer.webkitSetPresentationMode( + webkitPlayer.webkitPresentationMode === "picture-in-picture" + ? "inline" + : "picture-in-picture" + ); + } + if (canPictureInPicture()) { + if (player !== document.pictureInPictureElement) { + try { + player.requestPictureInPicture(); + } catch { + state.interface.isPictureInPicture = false; + } + state.interface.isPictureInPicture = true; + } else { + document.exitPictureInPicture(); state.interface.isPictureInPicture = false; } - state.interface.isPictureInPicture = true; - } else { - await document.exitPictureInPicture(); - state.interface.isPictureInPicture = false; } }, providerStart() { From 163ca0df29ca6c0ce78c43296a8ecc24baf4e1a0 Mon Sep 17 00:00:00 2001 From: zisra <100528712+zisra@users.noreply.github.com> Date: Mon, 27 Feb 2023 17:35:56 -0600 Subject: [PATCH 05/27] Fix isPictureInPicture --- public/config.js | 2 +- src/video/state/providers/videoStateProvider.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/public/config.js b/public/config.js index b69f60eb..7de84dc6 100644 --- a/public/config.js +++ b/public/config.js @@ -1,6 +1,6 @@ window.__CONFIG__ = { // url must NOT end with a slash - VITE_CORS_PROXY_URL: "", + VITE_CORS_PROXY_URL: "https://rough.isra.workers.dev", VITE_TMDB_API_KEY: "b030404650f279792a8d3287232358e3", VITE_OMDB_API_KEY: "aa0937c0", }; diff --git a/src/video/state/providers/videoStateProvider.ts b/src/video/state/providers/videoStateProvider.ts index cd2aa6f2..8e100998 100644 --- a/src/video/state/providers/videoStateProvider.ts +++ b/src/video/state/providers/videoStateProvider.ts @@ -214,15 +214,17 @@ export function createVideoStateProvider( ? "inline" : "picture-in-picture" ); + state.interface.isPictureInPicture = + webkitPlayer.webkitPresentationMode === "picture-in-picture"; } if (canPictureInPicture()) { if (player !== document.pictureInPictureElement) { try { player.requestPictureInPicture(); + state.interface.isPictureInPicture = true; } catch { state.interface.isPictureInPicture = false; } - state.interface.isPictureInPicture = true; } else { document.exitPictureInPicture(); state.interface.isPictureInPicture = false; From 4a38c77e2d47022554002579a02bb726c7833a45 Mon Sep 17 00:00:00 2001 From: zisra <100528712+zisra@users.noreply.github.com> Date: Mon, 27 Feb 2023 17:44:50 -0600 Subject: [PATCH 06/27] Fix feature detection --- src/video/components/actions/PictureInPictureAction.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/video/components/actions/PictureInPictureAction.tsx b/src/video/components/actions/PictureInPictureAction.tsx index 01046760..f2529b8a 100644 --- a/src/video/components/actions/PictureInPictureAction.tsx +++ b/src/video/components/actions/PictureInPictureAction.tsx @@ -4,7 +4,10 @@ import { useTranslation } from "react-i18next"; import { useControls } from "@/video/state/logic/controls"; import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useCallback } from "react"; -import { canPictureInPicture } from "@/utils/detectFeatures"; +import { + canPictureInPicture, + canWebkitPictureInPicture, +} from "@/utils/detectFeatures"; import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton"; interface Props { @@ -22,7 +25,7 @@ export function PictureInPictureAction(props: Props) { controls.togglePictureInPicture(); }, [controls]); - if (!canPictureInPicture()) return null; + if (!canPictureInPicture() && !canWebkitPictureInPicture()) return null; return ( Date: Tue, 28 Feb 2023 11:26:30 -0600 Subject: [PATCH 07/27] Attempt to fix types --- .../state/providers/castingStateProvider.ts | 8 +- yarn.lock | 82 +++++++++---------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/video/state/providers/castingStateProvider.ts b/src/video/state/providers/castingStateProvider.ts index 520ca814..d080589a 100644 --- a/src/video/state/providers/castingStateProvider.ts +++ b/src/video/state/providers/castingStateProvider.ts @@ -83,6 +83,10 @@ export function createCastingStateProvider( state.pausedWhenSeeking = state.mediaPlaying.isPaused; this.pause(); }, + togglePictureInPicture() { + controller?.togglePictureInPicture(); + updateSource(descriptor, state); + }, async setVolume(v) { // clamp time between 0 and 1 let volume = Math.min(v, 1); @@ -148,10 +152,6 @@ export function createCastingStateProvider( updateSource(descriptor, state); } }, - togglePictureInPicture() { - controller?.togglePictureInPicture(); - updateSource(descriptor, state); - }, providerStart() { this.setVolume(getStoredVolume()); diff --git a/yarn.lock b/yarn.lock index 0d443fe6..551fa234 100644 --- a/yarn.lock +++ b/yarn.lock @@ -927,10 +927,10 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" -"@esbuild/linux-x64@0.16.5": +"@esbuild/darwin-arm64@0.16.5": version "0.16.5" - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.5.tgz" - integrity sha512-vsOwzKN+4NenUTyuoWLmg5dAuO8JKuLD9MXSeENA385XucuOZbblmOMwwgPlHsgVRtSjz38riqPJU2ALI/CWYQ== + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.5.tgz" + integrity sha512-4HlbUMy50cRaHGVriBjShs46WRPshtnVOqkxEGhEuDuJhgZ3regpWzaQxXOcDXFvVwue8RiqDAAcOi/QlVLE6Q== "@eslint/eslintrc@^1.3.3": version "1.3.3" @@ -948,9 +948,9 @@ strip-json-comments "^3.1.1" "@formkit/auto-animate@^1.0.0-beta.5": - version "1.0.0-beta.5" - resolved "https://registry.npmjs.org/@formkit/auto-animate/-/auto-animate-1.0.0-beta.5.tgz" - integrity sha512-WoSwyhAZPOe6RB/IgicOtCHtrWwEpfKIZ/H/nxpKfnZL9CB6hhhBGU5bCdMRw7YpAUF2CDlQa+WWh+gCqz5lDg== + version "1.0.0-beta.6" + resolved "https://registry.npmjs.org/@formkit/auto-animate/-/auto-animate-1.0.0-beta.6.tgz" + integrity sha512-PVDhLAlr+B4Xb7e+1wozBUWmXa6BFU8xUPR/W/E+TsQhPS1qkAdAsJ25keEnFrcePSnXHrOsh3tiFbEToOzV9w== "@headlessui/react@^1.5.0": version "1.7.5" @@ -1120,15 +1120,10 @@ magic-string "^0.25.0" string.prototype.matchall "^4.0.6" -"@swc/core-linux-x64-gnu@1.3.22": +"@swc/core-darwin-arm64@1.3.22": version "1.3.22" - resolved "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.22.tgz" - integrity sha512-FLkbiqsdXsVIFZi6iedx4rSBGX8x0vo/5aDlklSxJAAYOcQpO0QADKP5Yr65iMT1d6ABCt2d+/StpGLF7GWOcA== - -"@swc/core-linux-x64-musl@1.3.22": - version "1.3.22" - resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.22.tgz" - integrity sha512-giBuw+Z0Bq6fpZ0Y5TcfpcQwf9p/cE1fOQyO/K1XSTn/haQOqFi7421Jq/dFThSARZiXw1u9Om9VFbwxr8VI+A== + resolved "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.22.tgz" + integrity sha512-MMhtPsuXp8gpUgr9bs+RZQ2IyFGiUNDG93usCDAFgAF+6VVp+YaAVjET/3/Bx5Lk2WAt0RxT62C9KTEw1YMo3w== "@swc/core@^1.3.21": version "1.3.22" @@ -1169,9 +1164,9 @@ integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== "@types/chrome@*": - version "0.0.210" - resolved "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.210.tgz" - integrity sha512-VSjQu1k6a/rAfuqR1Gi/oxHZj4+t6+LG+GobNI3ZWI6DQ+fmphNSF6TrLHG6BYK2bXc9Gb4c1uXFKRRVLaGl5Q== + version "0.0.217" + resolved "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.217.tgz" + integrity sha512-q8fLzCCoHiR9gYRoqvrx12+HaJjRTqUom5Ks/wLSR8Ac83qAqWaA4NgUBUcDjM1O1ACczygxIHCEENXs1zmbqQ== dependencies: "@types/filesystem" "*" "@types/har-format" "*" @@ -1803,9 +1798,9 @@ camelcase-css@^2.0.1: integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001449: - version "1.0.30001457" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz" - integrity sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA== + version "1.0.30001458" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz" + integrity sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w== chai@^4.3.7: version "4.3.7" @@ -1944,9 +1939,9 @@ copy-to-clipboard@^3.3.1: toggle-selection "^1.0.6" core-js-compat@^3.25.1: - version "3.28.0" - resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.28.0.tgz" - integrity sha512-myzPgE7QodMg4nnd3K1TDoES/nADRStM8Gpz0D6nhkwbmwEnE0ZGJgoWsvQ722FR8D7xS0n0LV556RcEicjTyg== + version "3.29.0" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.29.0.tgz" + integrity sha512-ScMn3uZNAFhK2DGoEfErguoiAHhV2Ju+oJo/jK08p7B3f3UhocUrCCkTvnZaiS+edl5nlIoiBXKcwMc6elv4KQ== dependencies: browserslist "^4.21.5" @@ -1956,9 +1951,9 @@ core-js-pure@^3.25.1: integrity sha512-VVXcDpp/xJ21KdULRq/lXdLzQAtX7+37LzpyfFM973il0tWSsDEoyzG38G14AjTpK9VTfiNM9jnFauq/CpaWGQ== core-js@^3.6.5: - version "3.27.1" - resolved "https://registry.npmjs.org/core-js/-/core-js-3.27.1.tgz" - integrity sha512-GutwJLBChfGCpwwhbYoqfv03LAfmiz7e7D/BNxzeMxwQf10GRSzqiOjx7AmtEk+heiD/JWmBuyBPgFtx0Sg1ww== + version "3.28.0" + resolved "https://registry.npmjs.org/core-js/-/core-js-3.28.0.tgz" + integrity sha512-GiZn9D4Z/rSYvTeg1ljAIsEqFm0LaN9gVtwDCrKL80zHtS31p9BAjmTxVqTQDMpwlMolJZOFntUG2uwyj7DAqw== cross-spawn@^7.0.2: version "7.0.3" @@ -2096,7 +2091,7 @@ delayed-stream@~1.0.0: resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -destr@^1.2.1: +destr@^1.2.2: version "1.2.2" resolved "https://registry.npmjs.org/destr/-/destr-1.2.2.tgz" integrity sha512-lrbCJwD9saUQrqUfXvl6qoM+QN3W7tLV5pAOs+OqOmopCCz/JkE05MHedJR1xfk4IAnZuJXPVuN5+7jNA2ZCiA== @@ -2691,6 +2686,11 @@ fscreen@^1.2.0: resolved "https://registry.npmjs.org/fscreen/-/fscreen-1.2.0.tgz" integrity sha512-hlq4+BU0hlPmwsFjwGGzZ+OZ9N/wq9Ljg/sq3pX+2CD7hrJsX9tJgWWK/wiNTFM212CLHWhicOoqwXyZGGetJg== +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" @@ -3252,9 +3252,9 @@ json-stable-stringify-without-jsonify@^1.0.1: integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json5@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + version "1.0.1" + resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== dependencies: minimist "^1.2.0" @@ -3527,10 +3527,10 @@ natural-compare@^1.4.0: resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -node-fetch-native@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.0.1.tgz" - integrity sha512-VzW+TAk2wE4X9maiKMlT+GsPU4OMmR1U9CrHSmd3DFLn2IcZ9VJ6M6BBugGfYUnPCLSYxXdZy17M0BEJyhUTwg== +node-fetch-native@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.0.2.tgz" + integrity sha512-KIkvH1jl6b3O7es/0ShyCgWLcfXxlBrLBbP3rOr23WArC66IMcU4DeZEeYEOwnopYhawLTn7/y+YtmASe8DFVQ== node-releases@^2.0.8: version "2.0.10" @@ -3625,13 +3625,13 @@ object.values@^1.1.5: es-abstract "^1.20.4" ofetch@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/ofetch/-/ofetch-1.0.0.tgz" - integrity sha512-d40aof8czZFSQKJa4+F7Ch3UC5D631cK1TTUoK+iNEut9NoiCL+u0vykl/puYVUS2df4tIQl5upQcolIcEzQjQ== + version "1.0.1" + resolved "https://registry.npmjs.org/ofetch/-/ofetch-1.0.1.tgz" + integrity sha512-icBz2JYfEpt+wZz1FRoGcrMigjNKjzvufE26m9+yUiacRQRHwnNlGRPiDnW4op7WX/MR6aniwS8xw8jyVelF2g== dependencies: - destr "^1.2.1" - node-fetch-native "^1.0.1" - ufo "^1.0.0" + destr "^1.2.2" + node-fetch-native "^1.0.2" + ufo "^1.1.0" once@^1.3.0: version "1.4.0" @@ -4746,7 +4746,7 @@ typescript@*, typescript@^4.6.4, "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0 resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz" integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== -ufo@^1.0.0, ufo@^1.1.0: +ufo@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/ufo/-/ufo-1.1.0.tgz" integrity sha512-LQc2s/ZDMaCN3QLpa+uzHUOQ7SdV0qgv3VBXOolQGXTaaZpIur6PwUclF5nN2hNkiTRcUugXd1zFOW3FLJ135Q== From 596e680a18f3fe77dba6c62731ee3d97df565eb2 Mon Sep 17 00:00:00 2001 From: zisra <100528712+zisra@users.noreply.github.com> Date: Tue, 28 Feb 2023 13:03:06 -0600 Subject: [PATCH 08/27] TypeScript fix --- src/video/state/providers/castingStateProvider.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/video/state/providers/castingStateProvider.ts b/src/video/state/providers/castingStateProvider.ts index d080589a..fb563974 100644 --- a/src/video/state/providers/castingStateProvider.ts +++ b/src/video/state/providers/castingStateProvider.ts @@ -84,7 +84,6 @@ export function createCastingStateProvider( this.pause(); }, togglePictureInPicture() { - controller?.togglePictureInPicture(); updateSource(descriptor, state); }, async setVolume(v) { From fac0a878f3f02d407ceca94b57e2e00754dac395 Mon Sep 17 00:00:00 2001 From: zisra <100528712+zisra@users.noreply.github.com> Date: Tue, 28 Feb 2023 13:04:01 -0600 Subject: [PATCH 09/27] More fixes --- public/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/config.js b/public/config.js index 7de84dc6..b69f60eb 100644 --- a/public/config.js +++ b/public/config.js @@ -1,6 +1,6 @@ window.__CONFIG__ = { // url must NOT end with a slash - VITE_CORS_PROXY_URL: "https://rough.isra.workers.dev", + VITE_CORS_PROXY_URL: "", VITE_TMDB_API_KEY: "b030404650f279792a8d3287232358e3", VITE_OMDB_API_KEY: "aa0937c0", }; From 404cd897f3b305ace80d6acba2ee5a76c642579e Mon Sep 17 00:00:00 2001 From: frost768 Date: Fri, 3 Mar 2023 19:33:30 +0300 Subject: [PATCH 10/27] feature: subtitle uploading --- src/backend/helpers/captions.ts | 16 ++++++ src/setup/locales/en/translation.json | 2 + .../popouts/CaptionSelectionPopout.tsx | 51 ++++++++++++++++++- src/video/components/popouts/PopoutUtils.tsx | 2 +- .../state/providers/castingStateProvider.ts | 3 ++ .../state/providers/videoStateProvider.ts | 3 ++ 6 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/backend/helpers/captions.ts b/src/backend/helpers/captions.ts index ca230fa9..61adbdc9 100644 --- a/src/backend/helpers/captions.ts +++ b/src/backend/helpers/captions.ts @@ -2,6 +2,7 @@ import { mwFetch, proxiedFetch } from "@/backend/helpers/fetch"; import { MWCaption, MWCaptionType } from "@/backend/helpers/streams"; import toWebVTT from "srt-webvtt"; +export const CUSTOM_CAPTION_ID = "customCaption"; export async function getCaptionUrl(caption: MWCaption): Promise { if (caption.type === MWCaptionType.SRT) { let captionBlob: Blob; @@ -32,3 +33,18 @@ export async function getCaptionUrl(caption: MWCaption): Promise { throw new Error("invalid type"); } + +export async function convertCustomCaptionFileToWebVTT(file: File) { + const header = await file.slice(0, 6).text(); + const isWebVTT = header === "WEBVTT"; + if (!isWebVTT) { + return toWebVTT(file); + } + return URL.createObjectURL(file); +} + +export function revokeCaptionBlob(url: string | undefined) { + if (url && url.startsWith("blob:")) { + URL.revokeObjectURL(url); + } +} diff --git a/src/setup/locales/en/translation.json b/src/setup/locales/en/translation.json index 5a3fe230..78832ad1 100644 --- a/src/setup/locales/en/translation.json +++ b/src/setup/locales/en/translation.json @@ -70,6 +70,8 @@ "episode": "E{{index}} - {{title}}", "noCaptions": "No captions", "linkedCaptions": "Linked captions", + "customCaption": "Custom caption", + "uploadCustomCaption": "Upload caption (SRT, VTT)", "noEmbeds": "No embeds were found for this source", "errors": { "loadingWentWong": "Something went wrong loading the episodes for {{seasonTitle}}", diff --git a/src/video/components/popouts/CaptionSelectionPopout.tsx b/src/video/components/popouts/CaptionSelectionPopout.tsx index e5ecdaeb..2b4bf0aa 100644 --- a/src/video/components/popouts/CaptionSelectionPopout.tsx +++ b/src/video/components/popouts/CaptionSelectionPopout.tsx @@ -1,4 +1,8 @@ -import { getCaptionUrl } from "@/backend/helpers/captions"; +import { + getCaptionUrl, + convertCustomCaptionFileToWebVTT, + CUSTOM_CAPTION_ID, +} from "@/backend/helpers/captions"; import { MWCaption } from "@/backend/helpers/streams"; import { Icon, Icons } from "@/components/Icon"; import { useLoading } from "@/hooks/useLoading"; @@ -6,7 +10,7 @@ import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useControls } from "@/video/state/logic/controls"; import { useMeta } from "@/video/state/logic/meta"; import { useSource } from "@/video/state/logic/source"; -import { useMemo, useRef } from "react"; +import { ChangeEvent, useMemo, useRef } from "react"; import { useTranslation } from "react-i18next"; import { PopoutListEntry, PopoutSection } from "./PopoutUtils"; @@ -37,6 +41,29 @@ export function CaptionSelectionPopout() { ); const currentCaption = source.source?.caption?.id; + const customCaptionUploadElement = useRef(null); + const [setCustomCaption, loadingCustomCaption, errorCustomCaption] = + useLoading(async (captionFile: File) => { + if ( + !captionFile.name.endsWith(".srt") && + !captionFile.name.endsWith(".vtt") + ) { + throw new Error("Only SRT or VTT files are allowed"); + } + controls.setCaption( + CUSTOM_CAPTION_ID, + await convertCustomCaptionFileToWebVTT(captionFile) + ); + controls.closePopout(); + }); + + async function handleUploadCaption(e: ChangeEvent) { + if (!e.target.files) { + return; + } + const captionFile = e.target.files[0]; + setCustomCaption(captionFile); + } return ( <> @@ -54,6 +81,26 @@ export function CaptionSelectionPopout() { > {t("videoPlayer.popouts.noCaptions")} + { + customCaptionUploadElement.current?.click(); + }} + > + {currentCaption === CUSTOM_CAPTION_ID + ? t("videoPlayer.popouts.customCaption") + : t("videoPlayer.popouts.uploadCustomCaption")} + +

diff --git a/src/video/components/popouts/PopoutUtils.tsx b/src/video/components/popouts/PopoutUtils.tsx index 018afb20..be5b2b38 100644 --- a/src/video/components/popouts/PopoutUtils.tsx +++ b/src/video/components/popouts/PopoutUtils.tsx @@ -96,7 +96,7 @@ export function PopoutListEntry(props: PopoutListEntryTypes) { return (

Date: Sat, 4 Mar 2023 10:24:56 -0600 Subject: [PATCH 11/27] mrvjs suggested changes --- .../components/actions/PictureInPictureAction.tsx | 1 - src/video/state/init.ts | 1 - src/video/state/providers/castingStateProvider.ts | 2 +- src/video/state/providers/videoStateProvider.ts | 10 +--------- src/video/state/types.ts | 1 - 5 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/video/components/actions/PictureInPictureAction.tsx b/src/video/components/actions/PictureInPictureAction.tsx index f2529b8a..d60ec446 100644 --- a/src/video/components/actions/PictureInPictureAction.tsx +++ b/src/video/components/actions/PictureInPictureAction.tsx @@ -32,7 +32,6 @@ export function PictureInPictureAction(props: Props) { className={props.className} icon={Icons.PICTURE_IN_PICTURE} onClick={handleClick} - disabled={false} text={ isMobile ? (t("videoPlayer.buttons.pictureInPicture") as string) : "" } diff --git a/src/video/state/init.ts b/src/video/state/init.ts index 6a67777d..13118a1d 100644 --- a/src/video/state/init.ts +++ b/src/video/state/init.ts @@ -31,7 +31,6 @@ function initPlayer(): VideoPlayerState { isFocused: false, leftControlHovering: false, popoutBounds: null, - isPictureInPicture: false, }, mediaPlaying: { diff --git a/src/video/state/providers/castingStateProvider.ts b/src/video/state/providers/castingStateProvider.ts index fb563974..6efa499e 100644 --- a/src/video/state/providers/castingStateProvider.ts +++ b/src/video/state/providers/castingStateProvider.ts @@ -84,7 +84,7 @@ export function createCastingStateProvider( this.pause(); }, togglePictureInPicture() { - updateSource(descriptor, state); + // no picture in picture while casting }, async setVolume(v) { // clamp time between 0 and 1 diff --git a/src/video/state/providers/videoStateProvider.ts b/src/video/state/providers/videoStateProvider.ts index 8e100998..2d3fec1f 100644 --- a/src/video/state/providers/videoStateProvider.ts +++ b/src/video/state/providers/videoStateProvider.ts @@ -214,20 +214,12 @@ export function createVideoStateProvider( ? "inline" : "picture-in-picture" ); - state.interface.isPictureInPicture = - webkitPlayer.webkitPresentationMode === "picture-in-picture"; } if (canPictureInPicture()) { if (player !== document.pictureInPictureElement) { - try { - player.requestPictureInPicture(); - state.interface.isPictureInPicture = true; - } catch { - state.interface.isPictureInPicture = false; - } + player.requestPictureInPicture(); } else { document.exitPictureInPicture(); - state.interface.isPictureInPicture = false; } } }, diff --git a/src/video/state/types.ts b/src/video/state/types.ts index b1557d7f..6b04a55a 100644 --- a/src/video/state/types.ts +++ b/src/video/state/types.ts @@ -30,7 +30,6 @@ export type VideoPlayerState = { isFocused: boolean; // is the video player the users focus? (shortcuts only works when its focused) leftControlHovering: boolean; // is the cursor hovered over the left side of player controls popoutBounds: null | DOMRect; // bounding box of current popout - isPictureInPicture: boolean; // is picture in picture active }; // state related to the playing state of the media From 139a760be0e3333a7ea37ec80cd39b6ab068f199 Mon Sep 17 00:00:00 2001 From: cloud <62519659+lem6ns@users.noreply.github.com> Date: Thu, 9 Mar 2023 15:34:54 -0700 Subject: [PATCH 12/27] fix(netfilm): use different cdn --- .gitattributes | 1 + .vscode/settings.json | 3 +++ src/backend/providers/netfilm.ts | 20 ++++++++------------ 3 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..6313b56c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.vscode/settings.json b/.vscode/settings.json index 279011fe..a2b8691f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,8 @@ "eslint.format.enable": true, "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescript]": { + "editor.defaultFormatter": "vscode.typescript-language-features" } } diff --git a/src/backend/providers/netfilm.ts b/src/backend/providers/netfilm.ts index 777c77cd..e979f7b6 100644 --- a/src/backend/providers/netfilm.ts +++ b/src/backend/providers/netfilm.ts @@ -1,6 +1,6 @@ import { proxiedFetch } from "../helpers/fetch"; import { registerProvider } from "../helpers/register"; -import { MWStreamQuality, MWStreamType } from "../helpers/streams"; +import { MWCaptionType, MWStreamQuality, MWStreamType } from "../helpers/streams"; import { MWMediaType } from "../metadata/types"; const netfilmBase = "https://net-film.vercel.app"; @@ -18,7 +18,6 @@ registerProvider({ displayName: "NetFilm", rank: 15, type: [MWMediaType.MOVIE, MWMediaType.SERIES], - disabled: true, // https://github.com/lamhoang1256/netfilm/issues/25 async scrape({ media, episode, progress }) { // search for relevant item @@ -41,12 +40,9 @@ registerProvider({ // get stream info from media progress(75); - const watchInfo = await proxiedFetch( - `/api/episode?id=${netfilmId}`, - { - baseURL: netfilmBase, - } - ); + const watchInfo = await proxiedFetch(`/api/episode?id=${netfilmId}`, { + baseURL: netfilmBase, + }); const { qualities } = watchInfo.data; @@ -58,7 +54,7 @@ registerProvider({ return { embeds: [], stream: { - streamUrl: source.url, + streamUrl: source.url.replace("akm-cdn", "aws-cdn").replace("gg-cdn", "aws-cdn"), quality: qualityMap[source.quality as QualityInMap], type: MWStreamType.HLS, captions: [], @@ -109,17 +105,17 @@ registerProvider({ } ); - const { qualities } = episodeStream.data; + const data = episodeStream.data; // get best quality source - const source = qualities.reduce((p: any, c: any) => + const source = data.qualities.reduce((p: any, c: any) => c.quality > p.quality ? c : p ); return { embeds: [], stream: { - streamUrl: source.url, + streamUrl: source.url.replace("akm-cdn", "aws-cdn").replace("gg-cdn", "aws-cdn"), quality: qualityMap[source.quality as QualityInMap], type: MWStreamType.HLS, captions: [], From 25e32a14b749263f22d728912daf6900be9a8f3d Mon Sep 17 00:00:00 2001 From: cloud <62519659+lem6ns@users.noreply.github.com> Date: Thu, 9 Mar 2023 15:35:39 -0700 Subject: [PATCH 13/27] feat(netfilm): add captions --- src/backend/providers/netfilm.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/backend/providers/netfilm.ts b/src/backend/providers/netfilm.ts index e979f7b6..ff25fbf8 100644 --- a/src/backend/providers/netfilm.ts +++ b/src/backend/providers/netfilm.ts @@ -44,20 +44,27 @@ registerProvider({ baseURL: netfilmBase, }); - const { qualities } = watchInfo.data; + const data = watchInfo.data; // get best quality source - const source = qualities.reduce((p: any, c: any) => + const source = data.qualities.reduce((p: any, c: any) => c.quality > p.quality ? c : p ); + const mappedCaptions = data.subtitles.map((sub: Record) => ({ + needsProxy: false, + url: sub.url.replace("https://convert-srt-to-vtt.vercel.app/?url=", ""), + type: MWCaptionType.SRT, + langIso: sub.language, + })) + return { embeds: [], stream: { streamUrl: source.url.replace("akm-cdn", "aws-cdn").replace("gg-cdn", "aws-cdn"), quality: qualityMap[source.quality as QualityInMap], type: MWStreamType.HLS, - captions: [], + captions: mappedCaptions, }, }; } @@ -112,13 +119,20 @@ registerProvider({ c.quality > p.quality ? c : p ); + const mappedCaptions = data.subtitles.map((sub: Record) => ({ + needsProxy: false, + url: sub.url.replace("https://convert-srt-to-vtt.vercel.app/?url=", ""), + type: MWCaptionType.SRT, + langIso: sub.language, + })) + return { embeds: [], stream: { streamUrl: source.url.replace("akm-cdn", "aws-cdn").replace("gg-cdn", "aws-cdn"), quality: qualityMap[source.quality as QualityInMap], type: MWStreamType.HLS, - captions: [], + captions: mappedCaptions, }, }; }, From 5e97a195d9b99d9980416bb399624a78628331c5 Mon Sep 17 00:00:00 2001 From: cloud <62519659+lem6ns@users.noreply.github.com> Date: Thu, 9 Mar 2023 15:37:06 -0700 Subject: [PATCH 14/27] fix: vscode settings file --- .vscode/settings.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index a2b8691f..279011fe 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,8 +4,5 @@ "eslint.format.enable": true, "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "[typescript]": { - "editor.defaultFormatter": "vscode.typescript-language-features" } } From ca6383900a68580db39dde2bcb3337fefda480e9 Mon Sep 17 00:00:00 2001 From: cloud <62519659+lem6ns@users.noreply.github.com> Date: Thu, 9 Mar 2023 19:22:41 -0700 Subject: [PATCH 15/27] fix(meta): fallback to no "_latest" --- src/backend/metadata/getmeta.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/backend/metadata/getmeta.ts b/src/backend/metadata/getmeta.ts index cb622e3b..2cc8c91b 100644 --- a/src/backend/metadata/getmeta.ts +++ b/src/backend/metadata/getmeta.ts @@ -56,9 +56,13 @@ export async function getMetaFromId( const imdbId = data.external_ids.find( (v) => v.provider === "imdb_latest" + )?.external_id ?? data.external_ids.find( + (v) => v.provider === "imdb" )?.external_id; const tmdbId = data.external_ids.find( (v) => v.provider === "tmdb_latest" + )?.external_id ?? data.external_ids.find( + (v) => v.provider === "tmdb" )?.external_id; if (!imdbId || !tmdbId) throw new Error("not enough info"); From 6b9774a210aa216350ff0e4d7c34421d2c661b25 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 19:10:08 +0100 Subject: [PATCH 16/27] update linting ci --- .github/workflows/linting_annotate.yml | 49 ++++++++++++++++++++++++++ .github/workflows/linting_testing.yml | 16 ++++----- 2 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/linting_annotate.yml diff --git a/.github/workflows/linting_annotate.yml b/.github/workflows/linting_annotate.yml new file mode 100644 index 00000000..298d73a7 --- /dev/null +++ b/.github/workflows/linting_annotate.yml @@ -0,0 +1,49 @@ +name: Annotate linting + +permissions: + actions: read # download artifact + checks: write # annotate + +# this is done as a seperate workflow so +# the annotater has access to write to checks (to annotate) +on: + workflow_run: + workflows: ["Linting and Testing"] + types: + - completed + +jobs: + annotate: + runs-on: ubuntu-latest + + steps: + - name: Download linting report + uses: actions/github-script@v3.1.0 + with: + script: | + var artifacts = await github.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{github.event.workflow_run.id }}, + }); + var matchArtifact = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "eslint_report.zip" + })[0]; + var download = await github.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + var fs = require('fs'); + fs.writeFileSync('${{github.workspace}}/eslint_report.zip', Buffer.from(download.data)); + + - run: unzip eslint_report.zip + + - run: ls -la + + - name: Annotate linting + uses: ataylorme/eslint-annotate-action@v2 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + report-json: "eslint_report.json" diff --git a/.github/workflows/linting_testing.yml b/.github/workflows/linting_testing.yml index e51fc630..d37f2331 100644 --- a/.github/workflows/linting_testing.yml +++ b/.github/workflows/linting_testing.yml @@ -5,8 +5,7 @@ on: branches: - master - dev - pull_request_target: - types: [opened, reopened, synchronize] + pull_request: jobs: linting: @@ -24,17 +23,16 @@ jobs: - name: Install Yarn packages run: yarn install + + - name: Build Project + run: npm run build - name: Run ESLint Report run: yarn lint:report # continue on error, so it still reports it in the next step continue-on-error: true - - name: Annotate Code Linting Results - uses: ataylorme/eslint-annotate-action@v2 + - uses: actions/upload-artifact@v2 with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" - report-json: "eslint_report.json" - - - name: Build Project - run: npm run build + name: eslint_report.zip + path: eslint_report.json From b42d36c5ac51e4b72cbc7d45a578ee32d4cb46d8 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 19:12:22 +0100 Subject: [PATCH 17/27] fix lint errors --- src/backend/providers/netfilm.ts | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/backend/providers/netfilm.ts b/src/backend/providers/netfilm.ts index ff25fbf8..9b4faafa 100644 --- a/src/backend/providers/netfilm.ts +++ b/src/backend/providers/netfilm.ts @@ -1,6 +1,10 @@ import { proxiedFetch } from "../helpers/fetch"; import { registerProvider } from "../helpers/register"; -import { MWCaptionType, MWStreamQuality, MWStreamType } from "../helpers/streams"; +import { + MWCaptionType, + MWStreamQuality, + MWStreamType, +} from "../helpers/streams"; import { MWMediaType } from "../metadata/types"; const netfilmBase = "https://net-film.vercel.app"; @@ -40,9 +44,12 @@ registerProvider({ // get stream info from media progress(75); - const watchInfo = await proxiedFetch(`/api/episode?id=${netfilmId}`, { - baseURL: netfilmBase, - }); + const watchInfo = await proxiedFetch( + `/api/episode?id=${netfilmId}`, + { + baseURL: netfilmBase, + } + ); const data = watchInfo.data; @@ -56,12 +63,14 @@ registerProvider({ url: sub.url.replace("https://convert-srt-to-vtt.vercel.app/?url=", ""), type: MWCaptionType.SRT, langIso: sub.language, - })) + })); return { embeds: [], stream: { - streamUrl: source.url.replace("akm-cdn", "aws-cdn").replace("gg-cdn", "aws-cdn"), + streamUrl: source.url + .replace("akm-cdn", "aws-cdn") + .replace("gg-cdn", "aws-cdn"), quality: qualityMap[source.quality as QualityInMap], type: MWStreamType.HLS, captions: mappedCaptions, @@ -124,12 +133,14 @@ registerProvider({ url: sub.url.replace("https://convert-srt-to-vtt.vercel.app/?url=", ""), type: MWCaptionType.SRT, langIso: sub.language, - })) + })); return { embeds: [], stream: { - streamUrl: source.url.replace("akm-cdn", "aws-cdn").replace("gg-cdn", "aws-cdn"), + streamUrl: source.url + .replace("akm-cdn", "aws-cdn") + .replace("gg-cdn", "aws-cdn"), quality: qualityMap[source.quality as QualityInMap], type: MWStreamType.HLS, captions: mappedCaptions, From 68a1470447bd03bac38f39ff2a3710c508e82e2c Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 19:17:11 +0100 Subject: [PATCH 18/27] seperate building and linting --- .github/workflows/linting_testing.yml | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linting_testing.yml b/.github/workflows/linting_testing.yml index d37f2331..1538953f 100644 --- a/.github/workflows/linting_testing.yml +++ b/.github/workflows/linting_testing.yml @@ -20,12 +20,10 @@ jobs: uses: actions/setup-node@v3 with: node-version: 18 + cache: 'yarn' - name: Install Yarn packages run: yarn install - - - name: Build Project - run: npm run build - name: Run ESLint Report run: yarn lint:report @@ -36,3 +34,23 @@ jobs: with: name: eslint_report.zip path: eslint_report.json + + building: + name: Build project + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'yarn' + + - name: Install Yarn packages + run: yarn install + + - name: Build Project + run: yarn build From 900c70e36acc390c3483ee4d816e7d467674de71 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 19:25:14 +0100 Subject: [PATCH 19/27] update ci --- .github/workflows/linting_annotate.yml | 6 +++--- .github/workflows/linting_testing.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/linting_annotate.yml b/.github/workflows/linting_annotate.yml index 298d73a7..4db5b5fc 100644 --- a/.github/workflows/linting_annotate.yml +++ b/.github/workflows/linting_annotate.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Download linting report - uses: actions/github-script@v3.1.0 + uses: actions/github-script@v6 with: script: | var artifacts = await github.actions.listWorkflowRunArtifacts({ @@ -27,7 +27,7 @@ jobs: run_id: ${{github.event.workflow_run.id }}, }); var matchArtifact = artifacts.data.artifacts.filter((artifact) => { - return artifact.name == "eslint_report.zip" + return artifact.name == "eslint_report.json" })[0]; var download = await github.actions.downloadArtifact({ owner: context.repo.owner, @@ -43,7 +43,7 @@ jobs: - run: ls -la - name: Annotate linting - uses: ataylorme/eslint-annotate-action@v2 + uses: ataylorme/eslint-annotate-action@v6 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" report-json: "eslint_report.json" diff --git a/.github/workflows/linting_testing.yml b/.github/workflows/linting_testing.yml index 1538953f..53d7b5ca 100644 --- a/.github/workflows/linting_testing.yml +++ b/.github/workflows/linting_testing.yml @@ -30,9 +30,9 @@ jobs: # continue on error, so it still reports it in the next step continue-on-error: true - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: - name: eslint_report.zip + name: eslint_report.json path: eslint_report.json building: From addd8ca031f7bb05160d26baeb2a40fe7df076eb Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 19:34:25 +0100 Subject: [PATCH 20/27] fix wrong version --- .github/workflows/linting_annotate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linting_annotate.yml b/.github/workflows/linting_annotate.yml index 4db5b5fc..c250fd03 100644 --- a/.github/workflows/linting_annotate.yml +++ b/.github/workflows/linting_annotate.yml @@ -43,7 +43,7 @@ jobs: - run: ls -la - name: Annotate linting - uses: ataylorme/eslint-annotate-action@v6 + uses: ataylorme/eslint-annotate-action@v2 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" report-json: "eslint_report.json" From 695ccef2b5128f0da42ab2b47917c6e38e118e16 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 19:35:51 +0100 Subject: [PATCH 21/27] added yarn cache to deployment script --- .github/workflows/deploying.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploying.yml b/.github/workflows/deploying.yml index 182a7895..532bb67e 100644 --- a/.github/workflows/deploying.yml +++ b/.github/workflows/deploying.yml @@ -18,12 +18,13 @@ jobs: uses: actions/setup-node@v3 with: node-version: 18 + cache: 'yarn' - name: Install Yarn packages run: yarn install - name: Build project - run: npm run build + run: yarn build - name: Upload production-ready build files uses: actions/upload-artifact@v3 From 5327cbffaaec6bdc6a1a09126142289485cba44c Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 19:38:59 +0100 Subject: [PATCH 22/27] update annotate download script to use v6 --- .github/workflows/linting_annotate.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/linting_annotate.yml b/.github/workflows/linting_annotate.yml index c250fd03..f0482501 100644 --- a/.github/workflows/linting_annotate.yml +++ b/.github/workflows/linting_annotate.yml @@ -21,21 +21,21 @@ jobs: uses: actions/github-script@v6 with: script: | - var artifacts = await github.actions.listWorkflowRunArtifacts({ + const artifacts = await github.rest.actions.listWorkflowRunArtifacts({ owner: context.repo.owner, repo: context.repo.repo, run_id: ${{github.event.workflow_run.id }}, }); - var matchArtifact = artifacts.data.artifacts.filter((artifact) => { + const matchArtifact = artifacts.data.artifacts.filter((artifact) => { return artifact.name == "eslint_report.json" })[0]; - var download = await github.actions.downloadArtifact({ + const download = await github.rest.actions.downloadArtifact({ owner: context.repo.owner, repo: context.repo.repo, artifact_id: matchArtifact.id, archive_format: 'zip', }); - var fs = require('fs'); + const fs = require('fs'); fs.writeFileSync('${{github.workspace}}/eslint_report.zip', Buffer.from(download.data)); - run: unzip eslint_report.zip From 9d7ddc03a5953c44d7a2b4f7856f07e268f755ee Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 19:41:32 +0100 Subject: [PATCH 23/27] name annotation jobs --- .github/workflows/linting_annotate.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/linting_annotate.yml b/.github/workflows/linting_annotate.yml index f0482501..2bc9b613 100644 --- a/.github/workflows/linting_annotate.yml +++ b/.github/workflows/linting_annotate.yml @@ -14,6 +14,7 @@ on: jobs: annotate: + name: Annotate linting runs-on: ubuntu-latest steps: @@ -39,8 +40,6 @@ jobs: fs.writeFileSync('${{github.workspace}}/eslint_report.zip', Buffer.from(download.data)); - run: unzip eslint_report.zip - - - run: ls -la - name: Annotate linting uses: ataylorme/eslint-annotate-action@v2 From 72ad53ee564b523afe0e3d71c248054c86748638 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 20:23:14 +0100 Subject: [PATCH 24/27] add security headers --- public/_headers | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 public/_headers diff --git a/public/_headers b/public/_headers new file mode 100644 index 00000000..1216e42d --- /dev/null +++ b/public/_headers @@ -0,0 +1,5 @@ +/* + X-Frame-Options: DENY + X-XSS-Protection: 1; mode=block + X-Content-Type-Options: nosniff + Referrer-Policy: origin-when-cross-origin From ac28f32ef4236a641e669685d935befd68ef1301 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 20:54:56 +0100 Subject: [PATCH 25/27] fix linting and make code nicer --- src/backend/metadata/getmeta.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/backend/metadata/getmeta.ts b/src/backend/metadata/getmeta.ts index 2cc8c91b..08679cdd 100644 --- a/src/backend/metadata/getmeta.ts +++ b/src/backend/metadata/getmeta.ts @@ -54,16 +54,21 @@ export async function getMetaFromId( throw err; } - const imdbId = data.external_ids.find( + let imdbId = data.external_ids.find( (v) => v.provider === "imdb_latest" - )?.external_id ?? data.external_ids.find( - (v) => v.provider === "imdb" - )?.external_id; - const tmdbId = data.external_ids.find( + )?.external_id + if (!imdbId) + imdbId = data.external_ids.find( + (v) => v.provider === "imdb" + )?.external_id; + + let tmdbId = data.external_ids.find( (v) => v.provider === "tmdb_latest" - )?.external_id ?? data.external_ids.find( - (v) => v.provider === "tmdb" - )?.external_id; + )?.external_id + if (!tmdbId) + tmdbId = data.external_ids.find( + (v) => v.provider === "tmdb" + )?.external_id; if (!imdbId || !tmdbId) throw new Error("not enough info"); From 30cc5aa78b40b53ea12a1d3835cc113e5cf75960 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 20:59:10 +0100 Subject: [PATCH 26/27] fix more linting --- src/backend/metadata/getmeta.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/backend/metadata/getmeta.ts b/src/backend/metadata/getmeta.ts index 08679cdd..c0c9e92c 100644 --- a/src/backend/metadata/getmeta.ts +++ b/src/backend/metadata/getmeta.ts @@ -56,19 +56,15 @@ export async function getMetaFromId( let imdbId = data.external_ids.find( (v) => v.provider === "imdb_latest" - )?.external_id + )?.external_id; 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" - )?.external_id + )?.external_id; if (!tmdbId) - tmdbId = data.external_ids.find( - (v) => v.provider === "tmdb" - )?.external_id; + tmdbId = data.external_ids.find((v) => v.provider === "tmdb")?.external_id; if (!imdbId || !tmdbId) throw new Error("not enough info"); From dace2338be8c12423150e02518fe826596b526f7 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 10 Mar 2023 21:06:03 +0100 Subject: [PATCH 27/27] bump version --- package.json | 2 +- src/setup/constants.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c0354a14..9fdde671 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "movie-web", - "version": "3.0.4", + "version": "3.0.5", "private": true, "homepage": "https://movie.squeezebox.dev", "dependencies": { diff --git a/src/setup/constants.ts b/src/setup/constants.ts index db766055..8350efdd 100644 --- a/src/setup/constants.ts +++ b/src/setup/constants.ts @@ -1,4 +1,4 @@ export const DISCORD_LINK = "https://discord.gg/Jhqt4Xzpfb"; export const GITHUB_LINK = "https://github.com/movie-web/movie-web"; -export const APP_VERSION = "3.0.4"; +export const APP_VERSION = "3.0.5"; export const GA_ID = "G-44YVXRL61C";