style: Improve touch screen compatibility
This commit is contained in:
@@ -33,6 +33,7 @@ const ActionButtons: React.FC<ActionButtonsProps> = ({
|
||||
const { visitorMode } = useVisitorMode();
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const isTouch = useMediaQuery('(hover: none), (pointer: coarse)');
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
@@ -57,7 +58,7 @@ const ActionButtons: React.FC<ActionButtonsProps> = ({
|
||||
</IconButton>
|
||||
|
||||
{!isMobile && (
|
||||
<Tooltip title={t('manage')}>
|
||||
<Tooltip title={t('manage')} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
onClick={onManageClick}
|
||||
|
||||
@@ -12,7 +12,8 @@ import {
|
||||
TableHead,
|
||||
TableRow,
|
||||
Tooltip,
|
||||
Typography
|
||||
Typography,
|
||||
useMediaQuery
|
||||
} from '@mui/material';
|
||||
import React from 'react';
|
||||
import { useLanguage } from '../../contexts/LanguageContext';
|
||||
@@ -40,6 +41,7 @@ const CollectionsTable: React.FC<CollectionsTableProps> = ({
|
||||
}) => {
|
||||
const { t } = useLanguage();
|
||||
const { visitorMode } = useVisitorMode();
|
||||
const isTouch = useMediaQuery('(hover: none), (pointer: coarse)');
|
||||
|
||||
return (
|
||||
<Box sx={{ mb: 6 }}>
|
||||
@@ -71,7 +73,7 @@ const CollectionsTable: React.FC<CollectionsTableProps> = ({
|
||||
<TableCell>{new Date(collection.createdAt).toLocaleDateString()}</TableCell>
|
||||
{!visitorMode && (
|
||||
<TableCell align="right">
|
||||
<Tooltip title={t('deleteCollection')}>
|
||||
<Tooltip title={t('deleteCollection')} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
color="error"
|
||||
onClick={() => onDelete(collection)}
|
||||
|
||||
@@ -24,7 +24,8 @@ import {
|
||||
TableSortLabel,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography
|
||||
Typography,
|
||||
useMediaQuery
|
||||
} from '@mui/material';
|
||||
import React, { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
@@ -96,6 +97,7 @@ const VideosTable: React.FC<VideosTableProps> = ({
|
||||
}) => {
|
||||
const { t } = useLanguage();
|
||||
const { visitorMode } = useVisitorMode();
|
||||
const isTouch = useMediaQuery('(hover: none), (pointer: coarse)');
|
||||
|
||||
// Local editing state
|
||||
const [editingVideoId, setEditingVideoId] = useState<string | null>(null);
|
||||
@@ -194,7 +196,7 @@ const VideosTable: React.FC<VideosTableProps> = ({
|
||||
<ThumbnailImage video={video} />
|
||||
</Link>
|
||||
{!visitorMode && (
|
||||
<Tooltip title={t('refreshThumbnail') || "Refresh Thumbnail"}>
|
||||
<Tooltip title={t('refreshThumbnail') || "Refresh Thumbnail"} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => onRefreshThumbnail(video.id)}
|
||||
@@ -296,7 +298,7 @@ const VideosTable: React.FC<VideosTableProps> = ({
|
||||
<TableCell>{formatSize(video.fileSize)}</TableCell>
|
||||
{!visitorMode && (
|
||||
<TableCell align="right">
|
||||
<Tooltip title={t('deleteVideo')}>
|
||||
<Tooltip title={t('deleteVideo')} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
color="error"
|
||||
onClick={() => onDeleteClick(video.id)}
|
||||
|
||||
@@ -161,7 +161,7 @@ const UpNextSidebar: React.FC<UpNextSidebarProps> = ({
|
||||
</Box>
|
||||
|
||||
{hoveredVideoId === relatedVideo.id && !isMobile && !isTouch && !visitorMode && (
|
||||
<Tooltip title={t('addToCollection')}>
|
||||
<Tooltip title={t('addToCollection')} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(e) => handleAddToCollectionClick(e, relatedVideo.id)}
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
Stack,
|
||||
Tooltip,
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
useTheme
|
||||
} from '@mui/material';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
@@ -59,6 +60,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useLanguage();
|
||||
const isTouch = useMediaQuery('(hover: none), (pointer: coarse)');
|
||||
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const [isPlaying, setIsPlaying] = useState<boolean>(false);
|
||||
@@ -593,7 +595,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
}, 200);
|
||||
}}
|
||||
>
|
||||
<Tooltip title={volume === 0 ? 'Unmute' : 'Mute'}>
|
||||
<Tooltip title={volume === 0 ? 'Unmute' : 'Mute'} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
onClick={handleVolumeClick}
|
||||
size="small"
|
||||
@@ -656,7 +658,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
</Box>
|
||||
|
||||
{/* Play/Pause */}
|
||||
<Tooltip title={isPlaying ? t('paused') : t('playing')}>
|
||||
<Tooltip title={isPlaying ? t('paused') : t('playing')} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
color={isPlaying ? "secondary" : "primary"}
|
||||
onClick={handlePlayPause}
|
||||
@@ -715,7 +717,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
{/* Subtitle Button (Mobile only, next to progress bar) */}
|
||||
{subtitles && subtitles.length > 0 && (
|
||||
<>
|
||||
<Tooltip title={subtitlesEnabled ? 'Subtitles' : 'Subtitles Off'}>
|
||||
<Tooltip title={subtitlesEnabled ? 'Subtitles' : 'Subtitles Off'} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
color={subtitlesEnabled ? "primary" : "default"}
|
||||
onClick={handleSubtitleClick}
|
||||
@@ -731,7 +733,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
{/* Right Side: Fullscreen, Subtitle, Loop (Desktop only) */}
|
||||
<Stack direction="row" spacing={0.5} alignItems="center" sx={{ ml: 1, display: { xs: 'none', sm: 'flex' } }}>
|
||||
{/* Fullscreen */}
|
||||
<Tooltip title={isFullscreen ? t('exitFullscreen') : t('enterFullscreen')}>
|
||||
<Tooltip title={isFullscreen ? t('exitFullscreen') : t('enterFullscreen')} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
onClick={handleToggleFullscreen}
|
||||
size="small"
|
||||
@@ -743,7 +745,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
{/* Subtitle */}
|
||||
{subtitles && subtitles.length > 0 && (
|
||||
<>
|
||||
<Tooltip title={subtitlesEnabled ? 'Subtitles' : 'Subtitles Off'}>
|
||||
<Tooltip title={subtitlesEnabled ? 'Subtitles' : 'Subtitles Off'} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
color={subtitlesEnabled ? "primary" : "default"}
|
||||
onClick={handleSubtitleClick}
|
||||
@@ -770,7 +772,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
)}
|
||||
|
||||
{/* Loop */}
|
||||
<Tooltip title={`${t('loop')} ${isLooping ? t('on') : t('off')}`}>
|
||||
<Tooltip title={`${t('loop')} ${isLooping ? t('on') : t('off')}`} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
color={isLooping ? "primary" : "default"}
|
||||
onClick={handleToggleLoop}
|
||||
@@ -791,7 +793,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
alignItems="center"
|
||||
sx={{ width: '100%', flexWrap: 'wrap' }}
|
||||
>
|
||||
<Tooltip title="-10m">
|
||||
<Tooltip title="-10m" disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
onClick={() => handleSeek(-600)}
|
||||
size="small"
|
||||
@@ -800,7 +802,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
<KeyboardDoubleArrowLeft />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="-1m">
|
||||
<Tooltip title="-1m" disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
onClick={() => handleSeek(-60)}
|
||||
size="small"
|
||||
@@ -809,7 +811,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
<FastRewind />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="-10s">
|
||||
<Tooltip title="-10s" disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
onClick={() => handleSeek(-10)}
|
||||
size="small"
|
||||
@@ -818,7 +820,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
<Replay10 />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="+10s">
|
||||
<Tooltip title="+10s" disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
onClick={() => handleSeek(10)}
|
||||
size="small"
|
||||
@@ -827,7 +829,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
<Forward10 />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="+1m">
|
||||
<Tooltip title="+1m" disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
onClick={() => handleSeek(60)}
|
||||
size="small"
|
||||
@@ -836,7 +838,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
<FastForward />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="+10m">
|
||||
<Tooltip title="+10m" disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
onClick={() => handleSeek(600)}
|
||||
size="small"
|
||||
@@ -849,7 +851,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
{/* Mobile: Fullscreen, Loop */}
|
||||
<Stack direction="row" spacing={0.5} alignItems="center" sx={{ display: { xs: 'flex', sm: 'none' }, ml: 1 }}>
|
||||
{/* Fullscreen */}
|
||||
<Tooltip title={isFullscreen ? t('exitFullscreen') : t('enterFullscreen')}>
|
||||
<Tooltip title={isFullscreen ? t('exitFullscreen') : t('enterFullscreen')} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
onClick={handleToggleFullscreen}
|
||||
size="small"
|
||||
@@ -859,7 +861,7 @@ const VideoControls: React.FC<VideoControlsProps> = ({
|
||||
</Tooltip>
|
||||
|
||||
{/* Loop */}
|
||||
<Tooltip title={`${t('loop')} ${isLooping ? t('on') : t('off')}`}>
|
||||
<Tooltip title={`${t('loop')} ${isLooping ? t('on') : t('off')}`} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
color={isLooping ? "primary" : "default"}
|
||||
onClick={handleToggleLoop}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Check, Close, Edit, ExpandLess, ExpandMore } from '@mui/icons-material';
|
||||
import { Box, Button, TextField, Tooltip, Typography } from '@mui/material';
|
||||
import { Box, Button, TextField, Tooltip, Typography, useMediaQuery } from '@mui/material';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { useLanguage } from '../../../contexts/LanguageContext';
|
||||
import { useVisitorMode } from '../../../contexts/VisitorModeContext';
|
||||
@@ -12,6 +12,7 @@ interface EditableTitleProps {
|
||||
const EditableTitle: React.FC<EditableTitleProps> = ({ title, onSave }) => {
|
||||
const { t } = useLanguage();
|
||||
const { visitorMode } = useVisitorMode();
|
||||
const isTouch = useMediaQuery('(hover: none), (pointer: coarse)');
|
||||
const [isEditingTitle, setIsEditingTitle] = useState<boolean>(false);
|
||||
const [editedTitle, setEditedTitle] = useState<string>('');
|
||||
const [isTitleExpanded, setIsTitleExpanded] = useState(false);
|
||||
@@ -106,7 +107,7 @@ const EditableTitle: React.FC<EditableTitleProps> = ({ title, onSave }) => {
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
|
||||
{!visitorMode && (
|
||||
<Tooltip title={t('editTitle')}>
|
||||
<Tooltip title={t('editTitle')} disableHoverListener={isTouch}>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={handleStartEditingTitle}
|
||||
@@ -117,7 +118,7 @@ const EditableTitle: React.FC<EditableTitleProps> = ({ title, onSave }) => {
|
||||
</Tooltip>
|
||||
)}
|
||||
{showExpandButton && (
|
||||
<Tooltip title={isTitleExpanded ? t('collapse') : t('expand')}>
|
||||
<Tooltip title={isTitleExpanded ? t('collapse') : t('expand')} disableHoverListener={isTouch}>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => setIsTitleExpanded(!isTitleExpanded)}
|
||||
|
||||
@@ -28,6 +28,7 @@ const VideoActionButtons: React.FC<VideoActionButtonsProps> = ({
|
||||
const { visitorMode } = useVisitorMode();
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const isTouch = useMediaQuery('(hover: none), (pointer: coarse)');
|
||||
const [playerMenuAnchor, setPlayerMenuAnchor] = useState<null | HTMLElement>(null);
|
||||
const videoUrl = useCloudStorageUrl(video.videoPath, 'video');
|
||||
|
||||
@@ -138,7 +139,7 @@ const VideoActionButtons: React.FC<VideoActionButtonsProps> = ({
|
||||
|
||||
const actionButtons = (
|
||||
<Stack direction="row" spacing={1}>
|
||||
<Tooltip title={t('playWith')}>
|
||||
<Tooltip title={t('playWith')} disableHoverListener={isTouch}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="inherit"
|
||||
@@ -169,7 +170,7 @@ const VideoActionButtons: React.FC<VideoActionButtonsProps> = ({
|
||||
<MenuItem onClick={() => handlePlayerSelect('copy')}>{t('copyUrl')}</MenuItem>
|
||||
</Menu>
|
||||
|
||||
<Tooltip title={t('share')}>
|
||||
<Tooltip title={t('share')} disableHoverListener={isTouch}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="inherit"
|
||||
@@ -181,7 +182,7 @@ const VideoActionButtons: React.FC<VideoActionButtonsProps> = ({
|
||||
</Tooltip>
|
||||
{!visitorMode && (
|
||||
<>
|
||||
<Tooltip title={t('addToCollection')}>
|
||||
<Tooltip title={t('addToCollection')} disableHoverListener={isTouch}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="inherit"
|
||||
@@ -191,7 +192,7 @@ const VideoActionButtons: React.FC<VideoActionButtonsProps> = ({
|
||||
<Add />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('delete')}>
|
||||
<Tooltip title={t('delete')} disableHoverListener={isTouch}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="inherit"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Notifications, NotificationsActive } from '@mui/icons-material';
|
||||
import { Avatar, Box, IconButton, Tooltip, Typography } from '@mui/material';
|
||||
import { Avatar, Box, IconButton, Tooltip, Typography, useMediaQuery } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { useLanguage } from '../../../contexts/LanguageContext';
|
||||
import { useVisitorMode } from '../../../contexts/VisitorModeContext';
|
||||
@@ -38,6 +38,7 @@ const VideoAuthorInfo: React.FC<VideoAuthorInfoProps> = ({
|
||||
}) => {
|
||||
const { t } = useLanguage();
|
||||
const { visitorMode } = useVisitorMode();
|
||||
const isTouch = useMediaQuery('(hover: none), (pointer: coarse)');
|
||||
const showSubscribeButton = (source === 'youtube' || source === 'bilibili') && !visitorMode;
|
||||
|
||||
const handleSubscribeClick = (e: React.MouseEvent) => {
|
||||
@@ -83,7 +84,7 @@ const VideoAuthorInfo: React.FC<VideoAuthorInfoProps> = ({
|
||||
</Typography>
|
||||
</Box>
|
||||
{showSubscribeButton && (
|
||||
<Tooltip title={isSubscribed ? t('unsubscribe') : t('subscribe')}>
|
||||
<Tooltip title={isSubscribed ? t('unsubscribe') : t('subscribe')} disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={handleSubscribeClick}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Add, Cast, Delete, MoreVert, Share } from '@mui/icons-material';
|
||||
import { Button, IconButton, Menu, Stack, Tooltip } from '@mui/material';
|
||||
import { Button, IconButton, Menu, Stack, Tooltip, useMediaQuery } from '@mui/material';
|
||||
import React, { useState } from 'react';
|
||||
import { useLanguage } from '../../../contexts/LanguageContext';
|
||||
import { useVisitorMode } from '../../../contexts/VisitorModeContext';
|
||||
@@ -23,6 +23,7 @@ const VideoKebabMenuButtons: React.FC<VideoKebabMenuButtonsProps> = ({
|
||||
}) => {
|
||||
const { t } = useLanguage();
|
||||
const { visitorMode } = useVisitorMode();
|
||||
const isTouch = useMediaQuery('(hover: none), (pointer: coarse)');
|
||||
const [kebabMenuAnchor, setKebabMenuAnchor] = useState<null | HTMLElement>(null);
|
||||
|
||||
const handleKebabMenuOpen = (event: React.MouseEvent<HTMLElement>) => {
|
||||
@@ -73,7 +74,7 @@ const VideoKebabMenuButtons: React.FC<VideoKebabMenuButtonsProps> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title="More actions">
|
||||
<Tooltip title="More actions" disableHoverListener={isTouch}>
|
||||
<IconButton
|
||||
onClick={handleKebabMenuOpen}
|
||||
sx={{
|
||||
@@ -110,7 +111,7 @@ const VideoKebabMenuButtons: React.FC<VideoKebabMenuButtonsProps> = ({
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" spacing={2} sx={{ justifyContent: 'flex-end' }}>
|
||||
<Tooltip title={t('playWith')}>
|
||||
<Tooltip title={t('playWith')} disableHoverListener={isTouch}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="inherit"
|
||||
@@ -120,7 +121,7 @@ const VideoKebabMenuButtons: React.FC<VideoKebabMenuButtonsProps> = ({
|
||||
<Cast />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('share')}>
|
||||
<Tooltip title={t('share')} disableHoverListener={isTouch}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="inherit"
|
||||
@@ -132,7 +133,7 @@ const VideoKebabMenuButtons: React.FC<VideoKebabMenuButtonsProps> = ({
|
||||
</Tooltip>
|
||||
{!visitorMode && (
|
||||
<>
|
||||
<Tooltip title={t('addToCollection')}>
|
||||
<Tooltip title={t('addToCollection')} disableHoverListener={isTouch}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="inherit"
|
||||
@@ -143,7 +144,7 @@ const VideoKebabMenuButtons: React.FC<VideoKebabMenuButtonsProps> = ({
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{onDelete && (
|
||||
<Tooltip title={t('delete')}>
|
||||
<Tooltip title={t('delete')} disableHoverListener={isTouch}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="inherit"
|
||||
|
||||
Reference in New Issue
Block a user