Browse Source

Merge pull request #596 from robertsspaceindustries/dev

Playlist download support
pull/598/head
mrjvs 2 years ago committed by GitHub
parent
commit
ed67c30e1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      src/assets/locales/en.json
  2. 87
      src/components/player/atoms/settings/Downloads.tsx
  3. 8
      src/components/player/atoms/settings/SettingsMenu.tsx

3
src/assets/locales/en.json

@ -188,8 +188,9 @@
"downloads": { "downloads": {
"title": "Download", "title": "Download",
"disclaimer": "Downloads are taken directly from the provider. movie-web does not have control over how the downloads are provided.", "disclaimer": "Downloads are taken directly from the provider. movie-web does not have control over how the downloads are provided.",
"hlsExplanation": "This media is a HLS stream which cannot be downloaded on movie-web.", "hlsDisclaimer": "Downloads are taken directly from the provider. movie-web does not have control over how the downloads are provided. Please note that you are downloading an HLS playlist, this is intended for users familiar with advanced multimedia streaming.",
"downloadVideo": "Download video", "downloadVideo": "Download video",
"downloadPlaylist": "Download playlist",
"downloadCaption": "Download current caption", "downloadCaption": "Download current caption",
"onPc": { "onPc": {
"1": "On PC, click the download button then, on the new page, right click the video and select <bold>Save video as</bold>", "1": "On PC, click the download button then, on the new page, right click the video and select <bold>Save video as</bold>",

87
src/components/player/atoms/settings/Downloads.tsx

@ -15,6 +15,7 @@ function useDownloadLink() {
const url = useMemo(() => { const url = useMemo(() => {
if (source?.type === "file" && currentQuality) if (source?.type === "file" && currentQuality)
return source.qualities[currentQuality]?.url ?? null; return source.qualities[currentQuality]?.url ?? null;
if (source?.type === "hls") return source.url;
return null; return null;
}, [source, currentQuality]); }, [source, currentQuality]);
return url; return url;
@ -42,6 +43,7 @@ export function DownloadView({ id }: { id: string }) {
const { t } = useTranslation(); const { t } = useTranslation();
const downloadUrl = useDownloadLink(); const downloadUrl = useDownloadLink();
const sourceType = usePlayerStore((s) => s.source?.type);
const selectedCaption = usePlayerStore((s) => s.caption?.selected); const selectedCaption = usePlayerStore((s) => s.caption?.selected);
const subtitleUrl = useMemo( const subtitleUrl = useMemo(
() => () =>
@ -60,36 +62,61 @@ export function DownloadView({ id }: { id: string }) {
</Menu.BackLink> </Menu.BackLink>
<Menu.Section> <Menu.Section>
<div> <div>
<Menu.ChevronLink onClick={() => router.navigate("/download/pc")}> {sourceType === "hls" ? (
{t("player.menus.downloads.onPc.title")} <>
</Menu.ChevronLink> <Menu.Paragraph marginClass="mb-6">
<Menu.ChevronLink onClick={() => router.navigate("/download/ios")}> <StyleTrans k="player.menus.downloads.hlsDisclaimer" />
{t("player.menus.downloads.onIos.title")} </Menu.Paragraph>
</Menu.ChevronLink>
<Menu.ChevronLink <Button className="w-full" href={downloadUrl} theme="purple">
onClick={() => router.navigate("/download/android")} {t("player.menus.downloads.downloadPlaylist")}
> </Button>
{t("player.menus.downloads.onAndroid.title")} <Button
</Menu.ChevronLink> className="w-full mt-2"
href={subtitleUrl ?? undefined}
<Menu.Divider /> disabled={!subtitleUrl}
theme="secondary"
<Menu.Paragraph marginClass="my-6"> download="subtitles.srt"
<StyleTrans k="player.menus.downloads.disclaimer" /> >
</Menu.Paragraph> {t("player.menus.downloads.downloadCaption")}
</Button>
<Button className="w-full" href={downloadUrl} theme="purple"> </>
{t("player.menus.downloads.downloadVideo")} ) : (
</Button> <>
<Button <Menu.ChevronLink onClick={() => router.navigate("/download/pc")}>
className="w-full mt-2" {t("player.menus.downloads.onPc.title")}
href={subtitleUrl ?? undefined} </Menu.ChevronLink>
disabled={!subtitleUrl} <Menu.ChevronLink
theme="secondary" onClick={() => router.navigate("/download/ios")}
download="subtitles.srt" >
> {t("player.menus.downloads.onIos.title")}
{t("player.menus.downloads.downloadCaption")} </Menu.ChevronLink>
</Button> <Menu.ChevronLink
onClick={() => router.navigate("/download/android")}
>
{t("player.menus.downloads.onAndroid.title")}
</Menu.ChevronLink>
<Menu.Divider />
<Menu.Paragraph marginClass="my-6">
<StyleTrans k="player.menus.downloads.disclaimer" />
</Menu.Paragraph>
<Button className="w-full" href={downloadUrl} theme="purple">
{t("player.menus.downloads.downloadVideo")}
</Button>
<Button
className="w-full mt-2"
href={subtitleUrl ?? undefined}
disabled={!subtitleUrl}
theme="secondary"
download="subtitles.srt"
>
{t("player.menus.downloads.downloadCaption")}
</Button>
</>
)}
</div> </div>
</Menu.Section> </Menu.Section>
</> </>

8
src/components/player/atoms/settings/SettingsMenu.tsx

@ -37,6 +37,8 @@ export function SettingsMenu({ id }: { id: string }) {
const source = usePlayerStore((s) => s.source); const source = usePlayerStore((s) => s.source);
const downloadable = source?.type === "file" || source?.type === "hls";
return ( return (
<Menu.Card> <Menu.Card>
<Menu.SectionTitle> <Menu.SectionTitle>
@ -58,12 +60,10 @@ export function SettingsMenu({ id }: { id: string }) {
<Menu.Link <Menu.Link
clickable clickable
onClick={() => onClick={() =>
router.navigate( router.navigate(downloadable ? "/download" : "/download/unable")
source?.type === "file" ? "/download" : "/download/unable",
)
} }
rightSide={<Icon className="text-xl" icon={Icons.DOWNLOAD} />} rightSide={<Icon className="text-xl" icon={Icons.DOWNLOAD} />}
className={source?.type === "file" ? "opacity-100" : "opacity-50"} className={downloadable ? "opacity-100" : "opacity-50"}
> >
{t("player.menus.settings.downloadItem")} {t("player.menus.settings.downloadItem")}
</Menu.Link> </Menu.Link>

Loading…
Cancel
Save