Fix fullscreen controls and refresh lint setup
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import js from '@eslint/js'
|
||||
import tsParser from '@typescript-eslint/parser'
|
||||
import tsPlugin from '@typescript-eslint/eslint-plugin'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||
import globals from 'globals'
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: ['dist/**', 'node_modules/**']
|
||||
},
|
||||
js.configs.recommended,
|
||||
{
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: {
|
||||
jsx: true
|
||||
}
|
||||
},
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.es2021
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
'@typescript-eslint': tsPlugin,
|
||||
'react-hooks': reactHooks,
|
||||
'react-refresh': reactRefresh
|
||||
},
|
||||
rules: {
|
||||
...tsPlugin.configs.recommended.rules,
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/exhaustive-deps': 'warn',
|
||||
'react-refresh/only-export-components': 'warn'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.config.{js,ts}', '**/*.config.{cjs,mjs}', 'vite.config.*', 'eslint.config.js'],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
+8
-6
@@ -22,21 +22,23 @@
|
||||
"build": "tsc && vite build",
|
||||
"build:lib": "tsc && vite build --config vite.config.lib.ts",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
|
||||
"lint": "eslint . --report-unused-disable-directives --max-warnings 0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.7.0",
|
||||
"globals": "^15.6.0",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
||||
"@typescript-eslint/parser": "^7.13.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.5.0",
|
||||
"@typescript-eslint/parser": "^8.5.0",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-refresh": "^0.4.7",
|
||||
"eslint": "^9.7.0",
|
||||
"eslint-plugin-react-hooks": "^5.0.0",
|
||||
"eslint-plugin-react-refresh": "^0.5.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"typescript": "^5.2.2",
|
||||
|
||||
@@ -42,7 +42,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
|
||||
onSeeked,
|
||||
onAudioTracksLoaded,
|
||||
}) => {
|
||||
const { videoRef, containerRef, setVideoState, toggleFullscreen, settings } = usePlayerContext()
|
||||
const { videoRef, setVideoState, toggleFullscreen, settings } = usePlayerContext()
|
||||
const lastClickTimeRef = React.useRef<number>(0)
|
||||
const [availableAudioTracks, setAvailableAudioTracks] = useState<AudioTrack[]>([])
|
||||
|
||||
@@ -368,7 +368,7 @@ export const VideoElement: React.FC<VideoElementProps> = ({
|
||||
}, [settings.audioTrack, availableAudioTracks, videoRef])
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className="video-container">
|
||||
<div className="video-container">
|
||||
<video
|
||||
ref={videoRef}
|
||||
className="video-element"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react'
|
||||
import { PlayerProvider } from '../contexts/PlayerContext'
|
||||
import { PlayerProvider, usePlayerContext } from '../contexts/PlayerContext'
|
||||
import { VideoElement } from './VideoElement'
|
||||
import { ControlsLayer } from './ControlsLayer'
|
||||
import type { VideoPlayerProps, AudioTrack } from '../types'
|
||||
@@ -14,6 +14,69 @@ if (!polyfillsInitialized) {
|
||||
polyfillsInitialized = true
|
||||
}
|
||||
|
||||
const VideoPlayerContent: React.FC<
|
||||
VideoPlayerProps & {
|
||||
audioTracks: AudioTrack[]
|
||||
onAudioTracksLoadedInternal: (tracks: AudioTrack[]) => void
|
||||
}
|
||||
> = ({
|
||||
src,
|
||||
poster,
|
||||
autoplay = false,
|
||||
loop = false,
|
||||
muted = false,
|
||||
controls = true,
|
||||
subtitles = [],
|
||||
keyboardShortcuts = true,
|
||||
pictureInPicture = true,
|
||||
className = '',
|
||||
style,
|
||||
onPlay,
|
||||
onPause,
|
||||
onEnded,
|
||||
onTimeUpdate,
|
||||
onVolumeChange,
|
||||
onError,
|
||||
onLoadedMetadata,
|
||||
onSeeking,
|
||||
onSeeked,
|
||||
audioTracks,
|
||||
onAudioTracksLoadedInternal,
|
||||
}) => {
|
||||
const { containerRef } = usePlayerContext()
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className={`video-player ${className}`} style={style}>
|
||||
<VideoElement
|
||||
src={src}
|
||||
poster={poster}
|
||||
autoplay={autoplay}
|
||||
loop={loop}
|
||||
muted={muted}
|
||||
subtitles={subtitles}
|
||||
onPlay={onPlay}
|
||||
onPause={onPause}
|
||||
onEnded={onEnded}
|
||||
onTimeUpdate={onTimeUpdate}
|
||||
onVolumeChange={onVolumeChange}
|
||||
onError={onError}
|
||||
onLoadedMetadata={onLoadedMetadata}
|
||||
onSeeking={onSeeking}
|
||||
onSeeked={onSeeked}
|
||||
onAudioTracksLoaded={onAudioTracksLoadedInternal}
|
||||
/>
|
||||
{controls && (
|
||||
<ControlsLayer
|
||||
keyboardShortcuts={keyboardShortcuts}
|
||||
pictureInPicture={pictureInPicture}
|
||||
subtitles={subtitles}
|
||||
audioTracks={audioTracks}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const VideoPlayer: React.FC<VideoPlayerProps> = ({
|
||||
src,
|
||||
poster,
|
||||
@@ -56,14 +119,18 @@ export const VideoPlayer: React.FC<VideoPlayerProps> = ({
|
||||
|
||||
return (
|
||||
<PlayerProvider initialMuted={muted}>
|
||||
<div className={`video-player ${className}`} style={style}>
|
||||
<VideoElement
|
||||
<VideoPlayerContent
|
||||
src={src}
|
||||
poster={poster}
|
||||
autoplay={autoplay}
|
||||
loop={loop}
|
||||
muted={muted}
|
||||
controls={controls}
|
||||
subtitles={subtitles}
|
||||
keyboardShortcuts={keyboardShortcuts}
|
||||
pictureInPicture={pictureInPicture}
|
||||
className={className}
|
||||
style={style}
|
||||
onPlay={onPlay}
|
||||
onPause={onPause}
|
||||
onEnded={onEnded}
|
||||
@@ -73,17 +140,9 @@ export const VideoPlayer: React.FC<VideoPlayerProps> = ({
|
||||
onLoadedMetadata={onLoadedMetadata}
|
||||
onSeeking={onSeeking}
|
||||
onSeeked={onSeeked}
|
||||
onAudioTracksLoaded={handleAudioTracksLoaded}
|
||||
/>
|
||||
{controls && (
|
||||
<ControlsLayer
|
||||
keyboardShortcuts={keyboardShortcuts}
|
||||
pictureInPicture={pictureInPicture}
|
||||
subtitles={subtitles}
|
||||
audioTracks={audioTracks}
|
||||
onAudioTracksLoadedInternal={handleAudioTracksLoaded}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</PlayerProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ export const SettingsButton: React.FC = () => {
|
||||
return (
|
||||
<button
|
||||
className="control-button settings-button"
|
||||
onMouseDown={(event) => event.stopPropagation()}
|
||||
onClick={toggleSettings}
|
||||
aria-label="Settings"
|
||||
title="Settings"
|
||||
|
||||
Reference in New Issue
Block a user