Skip to content

Commit

Permalink
feat: open in local player (#248)
Browse files Browse the repository at this point in the history
  • Loading branch information
kahosan authored May 3, 2024
1 parent e6e2580 commit 20a679d
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 23 deletions.
76 changes: 76 additions & 0 deletions src/components/video-player/external-player.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {
Box,
Button,
Flex,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalHeader,
ModalOverlay,
Text,
useColorMode,
} from '@chakra-ui/react';
import { useState } from 'react';

// source https://github.com/alist-org/alist-web/blob/d06a792fc183dff6aa784ec45c78bdaae3dea881/src/pages/home/previews/video_box.tsx#L20-L52
export const players: { icon: string; name: string; scheme: (url: string) => string }[] = [
// https://github.com/iina/iina/issues/4861
{ icon: 'iina', name: 'IINA', scheme: url => `iina://weblink?url=${url}` },
{ icon: 'potplayer', name: 'PotPlayer', scheme: url => `potplayer://${url}` },
{ icon: 'vlc', name: 'VLC', scheme: url => `vlc://${url}` },
{ icon: 'nplayer', name: 'nPlayer', scheme: url => `nplayer-${url}` },
{
icon: 'omniplayer',
name: 'OmniPlayer',
scheme: url => `omniplayer://weblink?url=${url}`,
},
{
icon: 'figplayer',
name: 'Fig Player',
scheme: url => `figplayer://weblink?url=${url}`,
},
{
icon: 'infuse',
name: 'Infuse',
scheme: url => `infuse://x-callback-url/play?url=${url}`,
},
{
icon: 'mxplayer',
name: 'MX Player',
scheme: url => `intent:${url}#Intent;package=com.mxtech.videoplayer.ad;end`,
},
{
icon: 'mxplayer-pro',
name: 'MX Player Pro',
scheme: url => `intent:${url}#Intent;package=com.mxtech.videoplayer.pro;end`,
},
];

export default function ExternalPlayer({ url }: { url: string }) {
const { colorMode } = useColorMode();
const [isOpen, setOpen] = useState(false);
return (
<Box bg={colorMode === 'light' ? 'blackAlpha.100' : 'whiteAlpha.100'} p="4" mt="4" h="50%">
<Text mb="4">使用本地播放器</Text>
<Flex gap={2} flexWrap="wrap">
<Button onClick={() => setOpen(true)} size="sm">
复制播放链接
</Button>
{players.map(player => (
<Button key={player.name} as="a" href={player.scheme(url)} rel="noreferrer" size="sm" fontSize="xs">
{player.name}
</Button>
))}
</Flex>
<Modal isOpen={isOpen} onClose={() => setOpen(false)}>
<ModalOverlay />
<ModalContent>
<ModalHeader pb={1}>复制链接</ModalHeader>
<ModalCloseButton />
<ModalBody pb={4}>{url}</ModalBody>
</ModalContent>
</Modal>
</Box>
);
}
50 changes: 27 additions & 23 deletions src/components/video-player/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, Spinner, useToast } from '@chakra-ui/react';
import { Box, Flex, Spinner, useToast } from '@chakra-ui/react';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

Expand All @@ -13,6 +13,7 @@ import { useColorMode } from '~/hooks/use-color-mode';
import { useVideoCurrentTime } from '~/hooks/use-watch-history';

import type { BangumiData } from '~/types/bangumi';
import ExternalPlayer from './external-player';

interface Props {
bangumiData: BangumiData;
Expand Down Expand Up @@ -147,28 +148,31 @@ export default function VideoPlayer({ bangumiData, danmakuApi, episode }: Props)

return (
<>
<Box
p="4"
rounded="4"
bg={colorMode === 'dark' ? 'whiteAlpha.200' : 'blackAlpha.200'}
boxShadow="base"
transition=".5s width"
w="full"
position="relative"
>
<Spinner
display={loading ? 'block' : 'none'}
zIndex="100"
position="absolute"
left="0"
right="0"
top="0"
bottom="0"
m="auto"
color="white"
/>
<Box id="DPlayer" ref={containerRef} />
</Box>
<Flex flexDirection="column">
<Box
p="4"
rounded="4"
bg={colorMode === 'dark' ? 'whiteAlpha.200' : 'blackAlpha.200'}
boxShadow="base"
transition=".5s width"
w="full"
position="relative"
>
<Spinner
display={loading ? 'block' : 'none'}
zIndex="100"
position="absolute"
left="0"
right="0"
top="0"
bottom="0"
m="auto"
color="white"
/>
<Box id="DPlayer" ref={containerRef} />
</Box>
<ExternalPlayer url={`${window.location.origin}/${encodeURIComponent(fileUrl.replace('./', ''))}`} />
</Flex>
<EpisodeCard boxShadow="base" setPlayState={setPlayState} bangumiData={episodeCardProps} />
</>
);
Expand Down

0 comments on commit 20a679d

Please sign in to comment.