播放视频时,与当前播放视频同文件夹的自动加入播放列表内,方便跳转与查看。并新增一个使用 IINA 外部播放器的按钮。
开发
功能比较简单,在原视频弹窗的基础上使用 useReaddirContext 获取所有视频文件,并使用 Menu 组件创建一个菜单列表。通过点击视频左边的“显示 icon”显示列表。
播放列表内置溢出滚动,高度与当前播放视频高度一致。
import React, { useState } from 'react'
import { isVideo } from '@/components/preview/ext-rxp'
import { useReaddirContext } from '@/app/path/readdir-context'
import { useReplacePathname } from '@/components/use-replace-pathname'
import { useVideoPathDispatch, useVideoPathStore } from '@/components/video-modal/video-path-context'
import { Button, Menu } from 'antd'
import styled from 'styled-components'
import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
const PlayListStyle = styled(Menu)`
position: absolute;
right: 0;
top: 0;
background: rgba(0, 0, 0, 0.5);
height: 100%;
max-width: 70%;
min-width: 30%;
overflow: scroll;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
`
const PlayHideListStyle = styled.div`
position: absolute;
right: 0;
top: 0;
cursor: pointer;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
transform: translateX(100%);
&:hover {
background: rgba(0, 0, 0, 0.5);
}
`
const PlayList: React.FC = () => {
const [open, changeOpen] = useState(false)
const readdir = useReaddirContext()
const { staticPath } = useReplacePathname()
const videoPathDispatch = useVideoPathDispatch()
const video_path = useVideoPathStore()
const video_list = readdir
.filter((item) => !item.is_directory && isVideo(item.name))
.map((item) => {
return {
key: staticPath(item.name),
label: item.name,
onClick: () => {},
}
})
return (
<>
{open && (
<PlayListStyle
defaultSelectedKeys={[video_path]}
onClick={(item) => {
videoPathDispatch(item.key)
}}
items={video_list}
/>
)}
<PlayHideListStyle onClick={() => changeOpen(!open)}>
<Button icon={open ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />} />
</PlayHideListStyle>
</>
)
}
export default PlayList
与 “video.js 播放器” 组件同级。并添加一个“openIINA”的方法。当点击按钮时浏览器将会唤起 iina 播放器,并开始播放当前视频。
...
import PlayList from '@/components/video-modal/play-list'
import { openIINA } from '@/components/video-modal/open-iina'
...
return (
<Modal
title={<>{filename}</>}
...
footer={<Button onClick={() => window.open(openIINA(`${window.location.origin}${video_path}`))}>IINA</Button>}
...
styles={{
body: {
height: '85vh',
position: 'relative',
},
}}
>
<PlayItem />
<PlayList />
</Modal>
)
}
export default VideoModal
openIINA 方法
export const openIINA = (path: string) => {
return `iina://weblink?url=${path}&new_window=1`
}
这里使用的 iina 协议,MacOS 安装 iina 播放器时可调用(其他播放器后续再添加)。
效果
截屏2023-12-31 11.13.42.png
将按钮加入 video.js 播放器内需要涉及到“插件开发”。与 React 开发有些割裂,遂将播放列表的按钮放在播放器外。