mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-10 01:18:55 -05:00
fix: Disable tooltip on touch devices (mobile and tablets)
This commit is contained in:
parent
119dc966fa
commit
57616c6b81
@ -8,6 +8,28 @@ html {
|
|||||||
box-sizing: inherit;
|
box-sizing: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Global tooltip disabling for touch devices */
|
||||||
|
@media (hover: none) and (pointer: coarse) {
|
||||||
|
/* Disable all CSS-based tooltips on touch devices */
|
||||||
|
.video-js .vjs-control:hover::after,
|
||||||
|
.video-js .vjs-control:focus::after,
|
||||||
|
.video-js .vjs-control:active::after,
|
||||||
|
.video-js button.vjs-button:hover span.vjs-control-text,
|
||||||
|
.vjs-chapter-marker:hover .vjs-chapter-marker-tooltip,
|
||||||
|
.vjs-chapter-floating-tooltip,
|
||||||
|
.vjs-sprite-preview-tooltip {
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exception: Allow intentional touch-activated tooltips */
|
||||||
|
.video-js .vjs-autoplay-toggle.touch-active::after {
|
||||||
|
opacity: 1 !important;
|
||||||
|
visibility: visible !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.playlist-items a {
|
.playlist-items a {
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
}
|
}
|
||||||
@ -1342,6 +1364,56 @@ button.vjs-button > .vjs-icon-placeholder:before {
|
|||||||
width: auto;
|
width: auto;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable all tooltips on touch devices */
|
||||||
|
.video-js .vjs-control:hover::after,
|
||||||
|
.video-js .vjs-control:focus::after,
|
||||||
|
.video-js .vjs-control:active::after {
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js .vjs-play-control:hover::after,
|
||||||
|
.video-js .vjs-mute-control:hover::after,
|
||||||
|
.video-js .vjs-volume-panel:hover::after,
|
||||||
|
.video-js .vjs-fullscreen-control:hover::after,
|
||||||
|
.video-js .vjs-picture-in-picture-control:hover::after,
|
||||||
|
.video-js .vjs-settings-control:hover::after,
|
||||||
|
.video-js .vjs-chapters-control:hover::after,
|
||||||
|
.video-js .vjs-autoplay-toggle:hover::after,
|
||||||
|
.video-js .vjs-next-video-control:hover::after,
|
||||||
|
.video-js .vjs-remaining-time:hover::after {
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable Video.js native control text tooltips on touch devices */
|
||||||
|
.video-js button.vjs-button:hover span.vjs-control-text {
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable chapter marker tooltips on touch devices */
|
||||||
|
.vjs-chapter-marker:hover .vjs-chapter-marker-tooltip {
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable chapter floating tooltips on touch devices */
|
||||||
|
.vjs-chapter-floating-tooltip,
|
||||||
|
.vjs-sprite-preview-tooltip {
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exception: Allow touch-activated autoplay tooltip on touch devices */
|
||||||
|
.video-js .vjs-autoplay-toggle.touch-active::after {
|
||||||
|
opacity: 1 !important;
|
||||||
|
visibility: visible !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
@media (min-width: 1200px) {
|
||||||
@ -1410,6 +1482,7 @@ button.vjs-button > .vjs-icon-placeholder:before {
|
|||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable all tooltips on tablets */
|
||||||
.video-js .vjs-control:hover::after,
|
.video-js .vjs-control:hover::after,
|
||||||
.video-js .vjs-control:focus::after,
|
.video-js .vjs-control:focus::after,
|
||||||
.video-js .vjs-control:active::after {
|
.video-js .vjs-control:active::after {
|
||||||
@ -1432,6 +1505,26 @@ button.vjs-button > .vjs-icon-placeholder:before {
|
|||||||
opacity: 0 !important;
|
opacity: 0 !important;
|
||||||
visibility: hidden !important;
|
visibility: hidden !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable Video.js native control text tooltips on tablets */
|
||||||
|
.video-js button.vjs-button:hover span.vjs-control-text {
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable chapter marker tooltips on tablets */
|
||||||
|
.vjs-chapter-marker:hover .vjs-chapter-marker-tooltip {
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable chapter floating tooltips on tablets */
|
||||||
|
.vjs-chapter-floating-tooltip,
|
||||||
|
.vjs-sprite-preview-tooltip {
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
@media (max-width: 1024px) {
|
||||||
@ -1531,6 +1624,7 @@ button.vjs-button > .vjs-icon-placeholder:before {
|
|||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable all tooltips on mobile */
|
||||||
.video-js .vjs-control:hover::after,
|
.video-js .vjs-control:hover::after,
|
||||||
.video-js .vjs-control:focus::after,
|
.video-js .vjs-control:focus::after,
|
||||||
.video-js .vjs-control:active::after {
|
.video-js .vjs-control:active::after {
|
||||||
@ -1554,6 +1648,27 @@ button.vjs-button > .vjs-icon-placeholder:before {
|
|||||||
visibility: hidden !important;
|
visibility: hidden !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable Video.js native control text tooltips on mobile */
|
||||||
|
.video-js button.vjs-button:hover span.vjs-control-text {
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable chapter marker tooltips on mobile */
|
||||||
|
.vjs-chapter-marker:hover .vjs-chapter-marker-tooltip {
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable chapter floating tooltips on mobile */
|
||||||
|
.vjs-chapter-floating-tooltip,
|
||||||
|
.vjs-sprite-preview-tooltip {
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exception: Allow touch-activated autoplay tooltip on mobile */
|
||||||
.video-js .vjs-autoplay-toggle.touch-active::after {
|
.video-js .vjs-autoplay-toggle.touch-active::after {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
@ -1569,9 +1684,6 @@ button.vjs-button > .vjs-icon-placeholder:before {
|
|||||||
.vjs-related-video-thumbnail {
|
.vjs-related-video-thumbnail {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
.vjs-chapter-floating-tooltip {
|
|
||||||
font-size: 11px !important;
|
|
||||||
}
|
|
||||||
.video-js-root-main .video-js.video-js-rounded-corners .custom-chapters-overlay {
|
.video-js-root-main .video-js.video-js-rounded-corners .custom-chapters-overlay {
|
||||||
border-bottom-left-radius: 12px !important;
|
border-bottom-left-radius: 12px !important;
|
||||||
border-bottom-right-radius: 12px !important;
|
border-bottom-right-radius: 12px !important;
|
||||||
@ -1665,6 +1777,7 @@ button.vjs-button > .vjs-icon-placeholder:before {
|
|||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable all tooltips on small mobile screens */
|
||||||
.video-js .vjs-control:hover::after,
|
.video-js .vjs-control:hover::after,
|
||||||
.video-js .vjs-control:focus::after,
|
.video-js .vjs-control:focus::after,
|
||||||
.video-js .vjs-control:active::after {
|
.video-js .vjs-control:active::after {
|
||||||
@ -1688,6 +1801,26 @@ button.vjs-button > .vjs-icon-placeholder:before {
|
|||||||
visibility: hidden !important;
|
visibility: hidden !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable Video.js native control text tooltips on small mobile */
|
||||||
|
.video-js button.vjs-button:hover span.vjs-control-text {
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable chapter marker tooltips on small mobile */
|
||||||
|
.vjs-chapter-marker:hover .vjs-chapter-marker-tooltip {
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable chapter floating tooltips on small mobile */
|
||||||
|
.vjs-chapter-floating-tooltip,
|
||||||
|
.vjs-sprite-preview-tooltip {
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
.vjs-related-video-thumbnail {
|
.vjs-related-video-thumbnail {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -113,6 +113,18 @@ class AutoplayToggleButton extends Button {
|
|||||||
|
|
||||||
// Add touch support for mobile tooltips
|
// Add touch support for mobile tooltips
|
||||||
addTouchSupport(button) {
|
addTouchSupport(button) {
|
||||||
|
// Check if device is touch-enabled
|
||||||
|
const isTouchDevice =
|
||||||
|
this.options_.isTouchDevice ||
|
||||||
|
'ontouchstart' in window ||
|
||||||
|
navigator.maxTouchPoints > 0 ||
|
||||||
|
navigator.msMaxTouchPoints > 0;
|
||||||
|
|
||||||
|
// Only add touch tooltip support on actual touch devices
|
||||||
|
if (!isTouchDevice) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let touchStartTime = 0;
|
let touchStartTime = 0;
|
||||||
let touchHandled = false;
|
let touchHandled = false;
|
||||||
|
|
||||||
@ -132,19 +144,20 @@ class AutoplayToggleButton extends Button {
|
|||||||
(e) => {
|
(e) => {
|
||||||
const touchDuration = Date.now() - touchStartTime;
|
const touchDuration = Date.now() - touchStartTime;
|
||||||
|
|
||||||
// Only show tooltip for quick taps (not swipes)
|
// Only show tooltip for quick taps (not swipes) and only on mobile screens
|
||||||
if (touchDuration < 500) {
|
const isMobileScreen = window.innerWidth <= 767;
|
||||||
|
if (touchDuration < 500 && isMobileScreen) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
// Show tooltip
|
// Show tooltip briefly
|
||||||
button.classList.add('touch-active');
|
button.classList.add('touch-active');
|
||||||
touchHandled = true;
|
touchHandled = true;
|
||||||
|
|
||||||
// Hide tooltip after delay
|
// Hide tooltip after shorter delay on mobile
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
button.classList.remove('touch-active');
|
button.classList.remove('touch-active');
|
||||||
}, 2000);
|
}, 1500);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ passive: false }
|
{ passive: false }
|
||||||
|
|||||||
@ -73,6 +73,18 @@ class ChapterMarkers extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupProgressBarHover() {
|
setupProgressBarHover() {
|
||||||
|
// Check if device is touch-enabled (tablet/mobile)
|
||||||
|
const isTouchDevice =
|
||||||
|
this.options_.isTouchDevice ||
|
||||||
|
'ontouchstart' in window ||
|
||||||
|
navigator.maxTouchPoints > 0 ||
|
||||||
|
navigator.msMaxTouchPoints > 0;
|
||||||
|
|
||||||
|
// Skip tooltip setup on touch devices
|
||||||
|
if (isTouchDevice) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const progressControl = this.player().getChild('controlBar').getChild('progressControl');
|
const progressControl = this.player().getChild('controlBar').getChild('progressControl');
|
||||||
if (!progressControl) return;
|
if (!progressControl) return;
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,18 @@ class SpritePreview extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupProgressBarHover() {
|
setupProgressBarHover() {
|
||||||
|
// Check if device is touch-enabled (tablet/mobile)
|
||||||
|
const isTouchDevice =
|
||||||
|
this.options_.isTouchDevice ||
|
||||||
|
'ontouchstart' in window ||
|
||||||
|
navigator.maxTouchPoints > 0 ||
|
||||||
|
navigator.msMaxTouchPoints > 0;
|
||||||
|
|
||||||
|
// Skip tooltip setup on touch devices
|
||||||
|
if (isTouchDevice) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const progressControl = this.player().getChild('controlBar').getChild('progressControl');
|
const progressControl = this.player().getChild('controlBar').getChild('progressControl');
|
||||||
if (!progressControl) return;
|
if (!progressControl) return;
|
||||||
|
|
||||||
|
|||||||
@ -183,6 +183,10 @@ class EmbedInfoOverlay extends Component {
|
|||||||
const player = this.player();
|
const player = this.player();
|
||||||
const overlay = this.el();
|
const overlay = this.el();
|
||||||
|
|
||||||
|
// Check if device is touch-enabled
|
||||||
|
const isTouchDevice =
|
||||||
|
'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
|
||||||
|
|
||||||
// Show/hide with controls
|
// Show/hide with controls
|
||||||
player.on('useractive', () => {
|
player.on('useractive', () => {
|
||||||
overlay.style.opacity = '1';
|
overlay.style.opacity = '1';
|
||||||
@ -190,8 +194,15 @@ class EmbedInfoOverlay extends Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
player.on('userinactive', () => {
|
player.on('userinactive', () => {
|
||||||
|
// On touch devices, keep overlay visible longer or don't hide it as aggressively
|
||||||
|
if (isTouchDevice) {
|
||||||
|
// Keep visible on touch devices when user inactive
|
||||||
|
overlay.style.opacity = '0.8';
|
||||||
|
overlay.style.visibility = 'visible';
|
||||||
|
} else {
|
||||||
overlay.style.opacity = '0';
|
overlay.style.opacity = '0';
|
||||||
overlay.style.visibility = 'hidden';
|
overlay.style.visibility = 'hidden';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Always show when paused
|
// Always show when paused
|
||||||
|
|||||||
@ -25,6 +25,11 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
|
|||||||
// Check if this is an embed player (disable next video and autoplay features)
|
// Check if this is an embed player (disable next video and autoplay features)
|
||||||
const isEmbedPlayer = videoId === 'video-embed';
|
const isEmbedPlayer = videoId === 'video-embed';
|
||||||
|
|
||||||
|
// Utility function to detect touch devices
|
||||||
|
const isTouchDevice = useMemo(() => {
|
||||||
|
return 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Environment-based development mode configuration
|
// Environment-based development mode configuration
|
||||||
const isDevMode = import.meta.env.VITE_DEV_MODE === 'true' || window.location.hostname.includes('vercel.app');
|
const isDevMode = import.meta.env.VITE_DEV_MODE === 'true' || window.location.hostname.includes('vercel.app');
|
||||||
// Safely access window.MEDIA_DATA with fallback using useMemo
|
// Safely access window.MEDIA_DATA with fallback using useMemo
|
||||||
@ -2152,6 +2157,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
|
|||||||
try {
|
try {
|
||||||
const autoplayToggleButton = new AutoplayToggleButton(playerRef.current, {
|
const autoplayToggleButton = new AutoplayToggleButton(playerRef.current, {
|
||||||
userPreferences: userPreferences.current,
|
userPreferences: userPreferences.current,
|
||||||
|
isTouchDevice: isTouchDevice,
|
||||||
});
|
});
|
||||||
// Add it before the chapters button (or at a suitable position)
|
// Add it before the chapters button (or at a suitable position)
|
||||||
const chaptersButtonIndex = chaptersButton
|
const chaptersButtonIndex = chaptersButton
|
||||||
@ -2378,16 +2384,19 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
|
|||||||
// Use original ChapterMarkers with sprite functionality when chapters exist
|
// Use original ChapterMarkers with sprite functionality when chapters exist
|
||||||
const chapterMarkers = new ChapterMarkers(playerRef.current, {
|
const chapterMarkers = new ChapterMarkers(playerRef.current, {
|
||||||
previewSprite: mediaData.previewSprite,
|
previewSprite: mediaData.previewSprite,
|
||||||
|
isTouchDevice: isTouchDevice,
|
||||||
});
|
});
|
||||||
seekBar.addChild(chapterMarkers);
|
seekBar.addChild(chapterMarkers);
|
||||||
} else if (mediaData.previewSprite) {
|
} else if (mediaData.previewSprite && !isTouchDevice) {
|
||||||
// Use separate SpritePreview component only when no chapters but sprite data exists
|
// Use separate SpritePreview component only when no chapters but sprite data exists
|
||||||
|
// Skip on touch devices to avoid unwanted tooltips
|
||||||
const spritePreview = new SpritePreview(playerRef.current, {
|
const spritePreview = new SpritePreview(playerRef.current, {
|
||||||
previewSprite: mediaData.previewSprite,
|
previewSprite: mediaData.previewSprite,
|
||||||
|
isTouchDevice: isTouchDevice,
|
||||||
});
|
});
|
||||||
seekBar.addChild(spritePreview);
|
seekBar.addChild(spritePreview);
|
||||||
|
|
||||||
// Setup sprite preview hover functionality
|
// Setup sprite preview hover functionality (only on non-touch devices)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
spritePreview.setupProgressBarHover();
|
spritePreview.setupProgressBarHover();
|
||||||
}, 100);
|
}, 100);
|
||||||
@ -2466,6 +2475,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
|
|||||||
userPreferences: userPreferences.current,
|
userPreferences: userPreferences.current,
|
||||||
qualities: availableQualities,
|
qualities: availableQualities,
|
||||||
hasSubtitles: hasSubtitles,
|
hasSubtitles: hasSubtitles,
|
||||||
|
isTouchDevice: isTouchDevice,
|
||||||
});
|
});
|
||||||
|
|
||||||
// If qualities change per video (e.g., via MEDIA_DATA update), refresh menu
|
// If qualities change per video (e.g., via MEDIA_DATA update), refresh menu
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user