@alfalab/core-components-gallery 7.2.3 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Component.js +51 -7
- package/Component.js.map +1 -1
- package/components/bottom-button/index.css +5 -5
- package/components/bottom-button/index.module.css.js +1 -1
- package/components/buttons/index.css +5 -5
- package/components/buttons/index.d.ts +3 -1
- package/components/buttons/index.js +49 -12
- package/components/buttons/index.js.map +1 -1
- package/components/buttons/index.module.css.js +1 -1
- package/components/header/Component.js +1 -0
- package/components/header/Component.js.map +1 -1
- package/components/header/index.css +3 -2
- package/components/header/index.module.css.js +1 -1
- package/components/header/index.module.css.js.map +1 -1
- package/components/header-info-block/Component.js +2 -1
- package/components/header-info-block/Component.js.map +1 -1
- package/components/header-info-block/index.css +4 -4
- package/components/header-info-block/index.module.css.js +1 -1
- package/components/header-mobile/index.css +6 -6
- package/components/header-mobile/index.module.css.js +1 -1
- package/components/image-preview/Component.js +2 -1
- package/components/image-preview/Component.js.map +1 -1
- package/components/image-preview/index.css +20 -20
- package/components/image-preview/index.module.css.js +1 -1
- package/components/image-preview/index.module.css.js.map +1 -1
- package/components/image-viewer/hooks.js +3 -2
- package/components/image-viewer/hooks.js.map +1 -1
- package/components/image-viewer/index.css +30 -31
- package/components/image-viewer/index.module.css.js +1 -1
- package/components/image-viewer/index.module.css.js.map +1 -1
- package/components/image-viewer/single.js +1 -0
- package/components/image-viewer/single.js.map +1 -1
- package/components/image-viewer/slide.js +3 -2
- package/components/image-viewer/slide.js.map +1 -1
- package/components/image-viewer/video/index.css +22 -10
- package/components/image-viewer/video/index.js +50 -15
- package/components/image-viewer/video/index.js.map +1 -1
- package/components/image-viewer/video/index.module.css.js +1 -1
- package/components/image-viewer/video/index.module.css.js.map +1 -1
- package/components/info-bar/Component.js +1 -0
- package/components/info-bar/Component.js.map +1 -1
- package/components/info-bar/index.css +3 -3
- package/components/info-bar/index.module.css.js +1 -1
- package/components/navigation-bar/Component.js +56 -26
- package/components/navigation-bar/Component.js.map +1 -1
- package/components/navigation-bar/index.css +21 -11
- package/components/navigation-bar/index.module.css.js +1 -1
- package/components/navigation-bar/index.module.css.js.map +1 -1
- package/components/subtitles/index.css +3 -3
- package/components/subtitles/index.module.css.js +1 -1
- package/constants.d.ts +1 -1
- package/constants.js +1 -1
- package/constants.js.map +1 -1
- package/cssm/Component.js +51 -7
- package/cssm/Component.js.map +1 -1
- package/cssm/components/buttons/index.d.ts +3 -1
- package/cssm/components/buttons/index.js +54 -17
- package/cssm/components/buttons/index.js.map +1 -1
- package/cssm/components/header/Component.js +1 -0
- package/cssm/components/header/Component.js.map +1 -1
- package/cssm/components/header/index.module.css +2 -1
- package/cssm/components/header-info-block/Component.js +2 -1
- package/cssm/components/header-info-block/Component.js.map +1 -1
- package/cssm/components/image-preview/Component.js +2 -1
- package/cssm/components/image-preview/Component.js.map +1 -1
- package/cssm/components/image-preview/index.module.css +3 -3
- package/cssm/components/image-viewer/hooks.js +3 -2
- package/cssm/components/image-viewer/hooks.js.map +1 -1
- package/cssm/components/image-viewer/index.module.css +2 -3
- package/cssm/components/image-viewer/single.js +1 -0
- package/cssm/components/image-viewer/single.js.map +1 -1
- package/cssm/components/image-viewer/slide.js +3 -2
- package/cssm/components/image-viewer/slide.js.map +1 -1
- package/cssm/components/image-viewer/video/index.js +50 -15
- package/cssm/components/image-viewer/video/index.js.map +1 -1
- package/cssm/components/image-viewer/video/index.module.css +15 -3
- package/cssm/components/info-bar/Component.js +1 -0
- package/cssm/components/info-bar/Component.js.map +1 -1
- package/cssm/components/navigation-bar/Component.js +56 -26
- package/cssm/components/navigation-bar/Component.js.map +1 -1
- package/cssm/components/navigation-bar/index.module.css +13 -3
- package/cssm/constants.d.ts +1 -1
- package/cssm/constants.js +1 -1
- package/cssm/constants.js.map +1 -1
- package/cssm/hooks/use-custom-subtitles.js +57 -11
- package/cssm/hooks/use-custom-subtitles.js.map +1 -1
- package/cssm/index.js +1 -0
- package/cssm/index.js.map +1 -1
- package/cssm/types.d.ts +4 -2
- package/cssm/utils/index.d.ts +1 -0
- package/cssm/utils/index.js +2 -0
- package/cssm/utils/index.js.map +1 -1
- package/cssm/utils/modern-download.d.ts +6 -0
- package/cssm/utils/modern-download.js +113 -0
- package/cssm/utils/modern-download.js.map +1 -0
- package/esm/Component.js +51 -7
- package/esm/Component.js.map +1 -1
- package/esm/components/bottom-button/index.css +5 -5
- package/esm/components/bottom-button/index.module.css.js +1 -1
- package/esm/components/buttons/index.css +5 -5
- package/esm/components/buttons/index.d.ts +3 -1
- package/esm/components/buttons/index.js +50 -13
- package/esm/components/buttons/index.js.map +1 -1
- package/esm/components/buttons/index.module.css.js +1 -1
- package/esm/components/header/Component.js +1 -0
- package/esm/components/header/Component.js.map +1 -1
- package/esm/components/header/index.css +3 -2
- package/esm/components/header/index.module.css.js +1 -1
- package/esm/components/header/index.module.css.js.map +1 -1
- package/esm/components/header-info-block/Component.js +2 -1
- package/esm/components/header-info-block/Component.js.map +1 -1
- package/esm/components/header-info-block/index.css +4 -4
- package/esm/components/header-info-block/index.module.css.js +1 -1
- package/esm/components/header-mobile/index.css +6 -6
- package/esm/components/header-mobile/index.module.css.js +1 -1
- package/esm/components/image-preview/Component.js +2 -1
- package/esm/components/image-preview/Component.js.map +1 -1
- package/esm/components/image-preview/index.css +20 -20
- package/esm/components/image-preview/index.module.css.js +1 -1
- package/esm/components/image-preview/index.module.css.js.map +1 -1
- package/esm/components/image-viewer/hooks.js +3 -2
- package/esm/components/image-viewer/hooks.js.map +1 -1
- package/esm/components/image-viewer/index.css +30 -31
- package/esm/components/image-viewer/index.module.css.js +1 -1
- package/esm/components/image-viewer/index.module.css.js.map +1 -1
- package/esm/components/image-viewer/single.js +1 -0
- package/esm/components/image-viewer/single.js.map +1 -1
- package/esm/components/image-viewer/slide.js +3 -2
- package/esm/components/image-viewer/slide.js.map +1 -1
- package/esm/components/image-viewer/video/index.css +22 -10
- package/esm/components/image-viewer/video/index.js +51 -16
- package/esm/components/image-viewer/video/index.js.map +1 -1
- package/esm/components/image-viewer/video/index.module.css.js +1 -1
- package/esm/components/image-viewer/video/index.module.css.js.map +1 -1
- package/esm/components/info-bar/Component.js +1 -0
- package/esm/components/info-bar/Component.js.map +1 -1
- package/esm/components/info-bar/index.css +3 -3
- package/esm/components/info-bar/index.module.css.js +1 -1
- package/esm/components/navigation-bar/Component.js +56 -25
- package/esm/components/navigation-bar/Component.js.map +1 -1
- package/esm/components/navigation-bar/index.css +21 -11
- package/esm/components/navigation-bar/index.module.css.js +1 -1
- package/esm/components/navigation-bar/index.module.css.js.map +1 -1
- package/esm/components/subtitles/index.css +3 -3
- package/esm/components/subtitles/index.module.css.js +1 -1
- package/esm/constants.d.ts +1 -1
- package/esm/constants.js +1 -1
- package/esm/constants.js.map +1 -1
- package/esm/hooks/use-custom-subtitles.js +57 -11
- package/esm/hooks/use-custom-subtitles.js.map +1 -1
- package/esm/index.css +9 -9
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/index.module.css.js +1 -1
- package/esm/types.d.ts +4 -2
- package/esm/utils/index.d.ts +1 -0
- package/esm/utils/index.js +1 -0
- package/esm/utils/index.js.map +1 -1
- package/esm/utils/modern-download.d.ts +6 -0
- package/esm/utils/modern-download.js +109 -0
- package/esm/utils/modern-download.js.map +1 -0
- package/hooks/use-custom-subtitles.js +57 -11
- package/hooks/use-custom-subtitles.js.map +1 -1
- package/index.css +9 -9
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/index.module.css.js +1 -1
- package/modern/Component.js +50 -7
- package/modern/Component.js.map +1 -1
- package/modern/components/bottom-button/index.css +5 -5
- package/modern/components/bottom-button/index.module.css.js +1 -1
- package/modern/components/buttons/index.css +5 -5
- package/modern/components/buttons/index.d.ts +3 -1
- package/modern/components/buttons/index.js +51 -12
- package/modern/components/buttons/index.js.map +1 -1
- package/modern/components/buttons/index.module.css.js +1 -1
- package/modern/components/header/index.css +3 -2
- package/modern/components/header/index.module.css.js +1 -1
- package/modern/components/header/index.module.css.js.map +1 -1
- package/modern/components/header-info-block/Component.js +1 -1
- package/modern/components/header-info-block/Component.js.map +1 -1
- package/modern/components/header-info-block/index.css +4 -4
- package/modern/components/header-info-block/index.module.css.js +1 -1
- package/modern/components/header-mobile/index.css +6 -6
- package/modern/components/header-mobile/index.module.css.js +1 -1
- package/modern/components/image-preview/Component.js +1 -1
- package/modern/components/image-preview/Component.js.map +1 -1
- package/modern/components/image-preview/index.css +20 -20
- package/modern/components/image-preview/index.module.css.js +1 -1
- package/modern/components/image-preview/index.module.css.js.map +1 -1
- package/modern/components/image-viewer/hooks.js +3 -2
- package/modern/components/image-viewer/hooks.js.map +1 -1
- package/modern/components/image-viewer/index.css +30 -31
- package/modern/components/image-viewer/index.module.css.js +1 -1
- package/modern/components/image-viewer/index.module.css.js.map +1 -1
- package/modern/components/image-viewer/slide.js +2 -2
- package/modern/components/image-viewer/slide.js.map +1 -1
- package/modern/components/image-viewer/video/index.css +22 -10
- package/modern/components/image-viewer/video/index.js +47 -12
- package/modern/components/image-viewer/video/index.js.map +1 -1
- package/modern/components/image-viewer/video/index.module.css.js +1 -1
- package/modern/components/image-viewer/video/index.module.css.js.map +1 -1
- package/modern/components/info-bar/index.css +3 -3
- package/modern/components/info-bar/index.module.css.js +1 -1
- package/modern/components/navigation-bar/Component.js +55 -25
- package/modern/components/navigation-bar/Component.js.map +1 -1
- package/modern/components/navigation-bar/index.css +21 -11
- package/modern/components/navigation-bar/index.module.css.js +1 -1
- package/modern/components/navigation-bar/index.module.css.js.map +1 -1
- package/modern/components/subtitles/index.css +3 -3
- package/modern/components/subtitles/index.module.css.js +1 -1
- package/modern/constants.d.ts +1 -1
- package/modern/constants.js +1 -1
- package/modern/constants.js.map +1 -1
- package/modern/hooks/use-custom-subtitles.js +56 -9
- package/modern/hooks/use-custom-subtitles.js.map +1 -1
- package/modern/index.css +9 -9
- package/modern/index.module.css.js +1 -1
- package/modern/types.d.ts +4 -2
- package/modern/utils/index.d.ts +1 -0
- package/modern/utils/index.js +1 -0
- package/modern/utils/index.js.map +1 -1
- package/modern/utils/modern-download.d.ts +6 -0
- package/modern/utils/modern-download.js +76 -0
- package/modern/utils/modern-download.js.map +1 -0
- package/moderncssm/Component.js +50 -7
- package/moderncssm/Component.js.map +1 -1
- package/moderncssm/components/buttons/index.d.ts +3 -1
- package/moderncssm/components/buttons/index.js +51 -12
- package/moderncssm/components/buttons/index.js.map +1 -1
- package/moderncssm/components/header/index.module.css +1 -1
- package/moderncssm/components/header-info-block/Component.js +1 -1
- package/moderncssm/components/header-info-block/Component.js.map +1 -1
- package/moderncssm/components/image-preview/Component.js +1 -1
- package/moderncssm/components/image-preview/Component.js.map +1 -1
- package/moderncssm/components/image-preview/index.module.css +2 -2
- package/moderncssm/components/image-viewer/hooks.js +3 -2
- package/moderncssm/components/image-viewer/hooks.js.map +1 -1
- package/moderncssm/components/image-viewer/index.module.css +2 -2
- package/moderncssm/components/image-viewer/slide.js +2 -2
- package/moderncssm/components/image-viewer/slide.js.map +1 -1
- package/moderncssm/components/image-viewer/video/index.js +47 -12
- package/moderncssm/components/image-viewer/video/index.js.map +1 -1
- package/moderncssm/components/image-viewer/video/index.module.css +16 -3
- package/moderncssm/components/navigation-bar/Component.js +55 -25
- package/moderncssm/components/navigation-bar/Component.js.map +1 -1
- package/moderncssm/components/navigation-bar/index.module.css +14 -2
- package/moderncssm/constants.d.ts +1 -1
- package/moderncssm/constants.js +1 -1
- package/moderncssm/constants.js.map +1 -1
- package/moderncssm/hooks/use-custom-subtitles.js +56 -9
- package/moderncssm/hooks/use-custom-subtitles.js.map +1 -1
- package/moderncssm/types.d.ts +4 -2
- package/moderncssm/utils/index.d.ts +1 -0
- package/moderncssm/utils/index.js +1 -0
- package/moderncssm/utils/index.js.map +1 -1
- package/moderncssm/utils/modern-download.d.ts +6 -0
- package/moderncssm/utils/modern-download.js +76 -0
- package/moderncssm/utils/modern-download.js.map +1 -0
- package/package.json +2 -2
- package/src/Component.tsx +63 -6
- package/src/components/buttons/index.tsx +157 -62
- package/src/components/header/index.module.css +1 -1
- package/src/components/header-info-block/Component.tsx +2 -2
- package/src/components/image-preview/Component.tsx +1 -1
- package/src/components/image-preview/index.module.css +2 -2
- package/src/components/image-viewer/hooks.ts +3 -2
- package/src/components/image-viewer/index.module.css +2 -2
- package/src/components/image-viewer/slide.tsx +2 -1
- package/src/components/image-viewer/video/index.module.css +16 -3
- package/src/components/image-viewer/video/index.tsx +62 -13
- package/src/components/navigation-bar/Component.tsx +68 -27
- package/src/components/navigation-bar/index.module.css +12 -2
- package/src/constants.ts +1 -1
- package/src/hooks/use-custom-subtitles.ts +72 -12
- package/src/types.ts +4 -2
- package/src/utils/index.ts +1 -0
- package/src/utils/modern-download.ts +107 -0
- package/types.d.ts +4 -2
- package/utils/index.d.ts +1 -0
- package/utils/index.js +2 -0
- package/utils/index.js.map +1 -1
- package/utils/modern-download.d.ts +6 -0
- package/utils/modern-download.js +113 -0
- package/utils/modern-download.js.map +1 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { type FC, useCallback, useContext, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import cn from 'classnames';
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
import { isClient } from '@alfalab/core-components-shared';
|
|
4
5
|
|
|
5
6
|
import { GalleryContext } from '../../context';
|
|
6
7
|
import { getImageKey, TestIds } from '../../utils';
|
|
@@ -9,13 +10,15 @@ import { ImagePreview } from '../image-preview';
|
|
|
9
10
|
import styles from './index.module.css';
|
|
10
11
|
|
|
11
12
|
const MIN_SCROLL_STEP = 24;
|
|
12
|
-
const
|
|
13
|
-
const SCROLL_THRESHOLD = 150; // Расстояние от границы, при котором начинается прокрутка
|
|
13
|
+
const DRAG_CLICK_THRESHOLD = 5;
|
|
14
14
|
|
|
15
15
|
export const NavigationBar: FC = () => {
|
|
16
16
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
17
|
+
const dragStartXRef = useRef<number>(0);
|
|
18
|
+
const dragStartScrollLeftRef = useRef<number>(0);
|
|
19
|
+
const suppressClickRef = useRef<boolean>(false);
|
|
17
20
|
|
|
18
|
-
const [
|
|
21
|
+
const [isDragging, setIsDragging] = useState<boolean>(false);
|
|
19
22
|
|
|
20
23
|
const { images, currentSlideIndex, setCurrentSlideIndex, getSwiper, setPlayingVideo, view } =
|
|
21
24
|
useContext(GalleryContext);
|
|
@@ -41,38 +44,72 @@ export const NavigationBar: FC = () => {
|
|
|
41
44
|
}
|
|
42
45
|
}, []);
|
|
43
46
|
|
|
44
|
-
const handlePreviewMouseDown = () => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const handlePreviewMouseUp = () => {
|
|
49
|
-
setIsNavMouseDowned(false);
|
|
50
|
-
if (containerRef.current) {
|
|
51
|
-
containerRef.current.style.scrollBehavior = 'auto'; // Отключаем плавность для резкой остановки
|
|
47
|
+
const handlePreviewMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
48
|
+
if (e.button !== 0 || !containerRef.current) {
|
|
49
|
+
return;
|
|
52
50
|
}
|
|
51
|
+
|
|
52
|
+
dragStartXRef.current = e.clientX;
|
|
53
|
+
dragStartScrollLeftRef.current = containerRef.current.scrollLeft;
|
|
54
|
+
suppressClickRef.current = false;
|
|
55
|
+
setIsDragging(true);
|
|
53
56
|
};
|
|
54
57
|
|
|
55
|
-
const
|
|
56
|
-
|
|
58
|
+
const handlePreviewMouseUp = useCallback(() => {
|
|
59
|
+
setIsDragging(false);
|
|
60
|
+
}, []);
|
|
57
61
|
|
|
62
|
+
const dragTo = useCallback((clientX: number) => {
|
|
58
63
|
const container = containerRef.current;
|
|
59
|
-
const { width: containerWidth, left: containerLeft } = container.getBoundingClientRect();
|
|
60
|
-
const mouseX = e.clientX;
|
|
61
64
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
if (!container) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const deltaX = clientX - dragStartXRef.current;
|
|
66
70
|
|
|
67
|
-
|
|
71
|
+
if (Math.abs(deltaX) > DRAG_CLICK_THRESHOLD) {
|
|
72
|
+
suppressClickRef.current = true;
|
|
68
73
|
}
|
|
69
|
-
// Если курсор близко к левой границе
|
|
70
|
-
else if (mouseX < containerLeft + SCROLL_THRESHOLD) {
|
|
71
|
-
const scrollValue = (mouseX - (containerLeft + SCROLL_THRESHOLD)) * SCROLL_SPEED;
|
|
72
74
|
|
|
73
|
-
|
|
75
|
+
container.scrollLeft = dragStartScrollLeftRef.current - deltaX;
|
|
76
|
+
}, []);
|
|
77
|
+
|
|
78
|
+
const handleMouseNavigationMove = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
79
|
+
if (!isDragging) {
|
|
80
|
+
return;
|
|
74
81
|
}
|
|
75
|
-
|
|
82
|
+
|
|
83
|
+
dragTo(e.clientX);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const handleClickCapture = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
87
|
+
if (!suppressClickRef.current) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
e.preventDefault();
|
|
92
|
+
e.stopPropagation();
|
|
93
|
+
suppressClickRef.current = false;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
if (!isClient() || !isDragging) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const handleDocumentMouseMove = (event: MouseEvent) => {
|
|
102
|
+
dragTo(event.clientX);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
document.addEventListener('mousemove', handleDocumentMouseMove);
|
|
106
|
+
document.addEventListener('mouseup', handlePreviewMouseUp);
|
|
107
|
+
|
|
108
|
+
return () => {
|
|
109
|
+
document.removeEventListener('mousemove', handleDocumentMouseMove);
|
|
110
|
+
document.removeEventListener('mouseup', handlePreviewMouseUp);
|
|
111
|
+
};
|
|
112
|
+
}, [dragTo, handlePreviewMouseUp, isDragging]);
|
|
76
113
|
|
|
77
114
|
const handlePreviewPosition = useCallback(
|
|
78
115
|
(preview: Element, containerWidth: number) => {
|
|
@@ -110,12 +147,16 @@ export const NavigationBar: FC = () => {
|
|
|
110
147
|
return (
|
|
111
148
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
112
149
|
<div
|
|
113
|
-
className={cn(styles.component, {
|
|
150
|
+
className={cn(styles.component, {
|
|
151
|
+
[styles.mobile]: view === 'mobile',
|
|
152
|
+
[styles.dragging]: isDragging,
|
|
153
|
+
})}
|
|
114
154
|
ref={containerRef}
|
|
115
155
|
data-test-id={TestIds.NAVIGATION_BAR}
|
|
116
156
|
onMouseDown={handlePreviewMouseDown}
|
|
117
157
|
onMouseUp={handlePreviewMouseUp}
|
|
118
158
|
onMouseMove={handleMouseNavigationMove}
|
|
159
|
+
onClickCapture={handleClickCapture}
|
|
119
160
|
>
|
|
120
161
|
{images.map((image, index) => {
|
|
121
162
|
const active = index === currentSlideIndex;
|
|
@@ -8,12 +8,22 @@
|
|
|
8
8
|
flex-shrink: 0;
|
|
9
9
|
overflow-x: auto;
|
|
10
10
|
box-sizing: border-box;
|
|
11
|
-
padding: var(--gap-12) var(--gap-
|
|
11
|
+
padding: var(--gap-12) var(--gap-32);
|
|
12
12
|
scrollbar-width: none;
|
|
13
13
|
background-color: var(--color-static-neutral-0-inverted);
|
|
14
|
+
cursor: grab;
|
|
15
|
+
user-select: none;
|
|
14
16
|
|
|
15
17
|
&.mobile {
|
|
16
|
-
padding: var(--gap-8)
|
|
18
|
+
padding: var(--gap-8);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&.dragging {
|
|
22
|
+
cursor: grabbing;
|
|
23
|
+
|
|
24
|
+
& * {
|
|
25
|
+
cursor: grabbing;
|
|
26
|
+
}
|
|
17
27
|
}
|
|
18
28
|
|
|
19
29
|
&::-webkit-scrollbar {
|
package/src/constants.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { useContext, useEffect, useState } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { GalleryContext } from '../context';
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const SUBTITLES_FADE_DURATION_SECONDS = 0.5;
|
|
6
6
|
|
|
7
7
|
export const useCustomSubtitles = () => {
|
|
8
8
|
const { getCurrentImageMeta } = useContext(GalleryContext);
|
|
@@ -15,14 +15,25 @@ export const useCustomSubtitles = () => {
|
|
|
15
15
|
const player = meta?.player?.current;
|
|
16
16
|
|
|
17
17
|
useEffect(() => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
if (!player) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const { textTracks } = player;
|
|
23
|
+
|
|
24
|
+
let textTrack: TextTrack | undefined;
|
|
25
|
+
let hideTimeoutId: ReturnType<typeof setTimeout> | undefined;
|
|
26
|
+
|
|
27
|
+
const clearHideTimeout = () => {
|
|
28
|
+
if (hideTimeoutId !== undefined) {
|
|
29
|
+
clearTimeout(hideTimeoutId);
|
|
30
|
+
hideTimeoutId = undefined;
|
|
21
31
|
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const syncSubtitles = () => {
|
|
35
|
+
clearHideTimeout();
|
|
22
36
|
|
|
23
|
-
const textTrack = [...(Array.from(player.textTracks) || [])].find(
|
|
24
|
-
(track) => track.kind === 'subtitles',
|
|
25
|
-
);
|
|
26
37
|
const activeCue = textTrack?.activeCues?.[0] as VTTCue | undefined;
|
|
27
38
|
|
|
28
39
|
if (!activeCue?.text) {
|
|
@@ -31,16 +42,65 @@ export const useCustomSubtitles = () => {
|
|
|
31
42
|
return;
|
|
32
43
|
}
|
|
33
44
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
player?.currentTime <= activeCue.endTime - SUBTITLES_ANIMATION_SPEED;
|
|
45
|
+
const fadeStartTime = activeCue.endTime - SUBTITLES_FADE_DURATION_SECONDS;
|
|
46
|
+
const isVisible = player.currentTime <= fadeStartTime;
|
|
37
47
|
|
|
38
48
|
setCurrentSub(activeCue.text);
|
|
39
49
|
setShowSub(isVisible);
|
|
40
|
-
|
|
50
|
+
|
|
51
|
+
if (!isVisible || player.paused || player.playbackRate <= 0) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const timeUntilFadeMs =
|
|
56
|
+
((fadeStartTime - player.currentTime) / player.playbackRate) * 1000;
|
|
57
|
+
|
|
58
|
+
hideTimeoutId = setTimeout(() => {
|
|
59
|
+
setShowSub(false);
|
|
60
|
+
}, timeUntilFadeMs);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const connectTextTrack = () => {
|
|
64
|
+
const nextTextTrack = Array.from(textTracks).find(
|
|
65
|
+
(track) => track.kind === 'subtitles',
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
if (nextTextTrack === textTrack) {
|
|
69
|
+
syncSubtitles();
|
|
70
|
+
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
textTrack?.removeEventListener('cuechange', syncSubtitles);
|
|
75
|
+
textTrack = nextTextTrack;
|
|
76
|
+
textTrack?.addEventListener('cuechange', syncSubtitles);
|
|
77
|
+
syncSubtitles();
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
player.addEventListener('play', syncSubtitles);
|
|
81
|
+
player.addEventListener('playing', syncSubtitles);
|
|
82
|
+
player.addEventListener('pause', clearHideTimeout);
|
|
83
|
+
player.addEventListener('waiting', clearHideTimeout);
|
|
84
|
+
player.addEventListener('seeking', clearHideTimeout);
|
|
85
|
+
player.addEventListener('seeked', syncSubtitles);
|
|
86
|
+
player.addEventListener('ratechange', syncSubtitles);
|
|
87
|
+
textTracks.addEventListener('addtrack', connectTextTrack);
|
|
88
|
+
textTracks.addEventListener('change', connectTextTrack);
|
|
89
|
+
|
|
90
|
+
connectTextTrack();
|
|
41
91
|
|
|
42
92
|
return () => {
|
|
43
|
-
|
|
93
|
+
clearHideTimeout();
|
|
94
|
+
textTrack?.removeEventListener('cuechange', syncSubtitles);
|
|
95
|
+
player.removeEventListener('play', syncSubtitles);
|
|
96
|
+
player.removeEventListener('playing', syncSubtitles);
|
|
97
|
+
player.removeEventListener('pause', clearHideTimeout);
|
|
98
|
+
player.removeEventListener('waiting', clearHideTimeout);
|
|
99
|
+
player.removeEventListener('seeking', clearHideTimeout);
|
|
100
|
+
player.removeEventListener('seeked', syncSubtitles);
|
|
101
|
+
player.removeEventListener('ratechange', syncSubtitles);
|
|
102
|
+
textTracks.removeEventListener('addtrack', connectTextTrack);
|
|
103
|
+
textTracks.removeEventListener('change', connectTextTrack);
|
|
44
104
|
};
|
|
45
105
|
}, [player]);
|
|
46
106
|
|
package/src/types.ts
CHANGED
|
@@ -44,10 +44,12 @@ export type ImageMeta =
|
|
|
44
44
|
height: number;
|
|
45
45
|
broken?: boolean;
|
|
46
46
|
player?: never;
|
|
47
|
+
loaded?: boolean;
|
|
47
48
|
}
|
|
48
49
|
| {
|
|
49
|
-
width?:
|
|
50
|
-
height?:
|
|
50
|
+
width?: number;
|
|
51
|
+
height?: number;
|
|
51
52
|
broken?: boolean;
|
|
52
53
|
player: RefObject<HTMLVideoElement>;
|
|
54
|
+
loaded?: boolean;
|
|
53
55
|
};
|
package/src/utils/index.ts
CHANGED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
const downloadWithBlob = (blob: Blob, fileName: string): void => {
|
|
2
|
+
const url = URL.createObjectURL(blob);
|
|
3
|
+
const link = document.createElement('a');
|
|
4
|
+
|
|
5
|
+
link.href = url;
|
|
6
|
+
link.download = fileName;
|
|
7
|
+
document.body.appendChild(link);
|
|
8
|
+
link.click();
|
|
9
|
+
document.body.removeChild(link);
|
|
10
|
+
setTimeout(() => URL.revokeObjectURL(url), 100);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const downloadWithLink = (url: string, fileName: string): void => {
|
|
14
|
+
const link = document.createElement('a');
|
|
15
|
+
|
|
16
|
+
link.href = url;
|
|
17
|
+
link.download = fileName;
|
|
18
|
+
link.target = '_blank';
|
|
19
|
+
link.rel = 'noopener noreferrer';
|
|
20
|
+
document.body.appendChild(link);
|
|
21
|
+
link.click();
|
|
22
|
+
document.body.removeChild(link);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const canUseBlobDownload = (): boolean =>
|
|
26
|
+
typeof fetch === 'function' &&
|
|
27
|
+
typeof URL.createObjectURL === 'function' &&
|
|
28
|
+
typeof URL.revokeObjectURL === 'function';
|
|
29
|
+
|
|
30
|
+
const canUseFileShare = (): boolean =>
|
|
31
|
+
typeof File === 'function' &&
|
|
32
|
+
typeof navigator !== 'undefined' &&
|
|
33
|
+
typeof navigator.share === 'function' &&
|
|
34
|
+
typeof navigator.canShare === 'function';
|
|
35
|
+
|
|
36
|
+
const canShareFiles = (files: File[]): boolean =>
|
|
37
|
+
canUseFileShare() && navigator.canShare({ files });
|
|
38
|
+
|
|
39
|
+
const getBlob = async (url: string): Promise<Blob> => {
|
|
40
|
+
const response = await fetch(url);
|
|
41
|
+
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
throw new Error('Network error');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return response.blob();
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const isAbortError = (error: unknown): boolean =>
|
|
50
|
+
typeof DOMException !== 'undefined' &&
|
|
51
|
+
error instanceof DOMException &&
|
|
52
|
+
error.name === 'AbortError';
|
|
53
|
+
|
|
54
|
+
export interface DownloadOptions {
|
|
55
|
+
url: string;
|
|
56
|
+
fileName?: string;
|
|
57
|
+
fileType?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const downloadFile = async ({
|
|
61
|
+
url,
|
|
62
|
+
fileName = 'download',
|
|
63
|
+
fileType,
|
|
64
|
+
}: DownloadOptions): Promise<void> => {
|
|
65
|
+
if (!canUseBlobDownload()) {
|
|
66
|
+
downloadWithLink(url, fileName);
|
|
67
|
+
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (canUseFileShare() && canShareFiles([new File([], fileName, { type: fileType })])) {
|
|
72
|
+
try {
|
|
73
|
+
const blob = await getBlob(url);
|
|
74
|
+
|
|
75
|
+
const file = new File([blob], fileName, { type: blob.type || fileType });
|
|
76
|
+
|
|
77
|
+
if (!canShareFiles([file])) {
|
|
78
|
+
downloadWithBlob(blob, fileName);
|
|
79
|
+
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
await navigator.share({
|
|
84
|
+
files: [file],
|
|
85
|
+
title: `Скачать ${fileName}`,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return;
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (isAbortError(error)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
downloadWithLink(url, fileName);
|
|
95
|
+
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
const blob = await getBlob(url);
|
|
102
|
+
|
|
103
|
+
downloadWithBlob(blob, fileName);
|
|
104
|
+
} catch {
|
|
105
|
+
downloadWithLink(url, fileName);
|
|
106
|
+
}
|
|
107
|
+
};
|
package/types.d.ts
CHANGED
|
@@ -40,9 +40,11 @@ export type ImageMeta = {
|
|
|
40
40
|
height: number;
|
|
41
41
|
broken?: boolean;
|
|
42
42
|
player?: never;
|
|
43
|
+
loaded?: boolean;
|
|
43
44
|
} | {
|
|
44
|
-
width?:
|
|
45
|
-
height?:
|
|
45
|
+
width?: number;
|
|
46
|
+
height?: number;
|
|
46
47
|
broken?: boolean;
|
|
47
48
|
player: RefObject<HTMLVideoElement>;
|
|
49
|
+
loaded?: boolean;
|
|
48
50
|
};
|
package/utils/index.d.ts
CHANGED
package/utils/index.js
CHANGED
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var splitFilename = require('./split-filename.js');
|
|
6
6
|
var utils = require('./utils.js');
|
|
7
7
|
var constants = require('./constants.js');
|
|
8
|
+
var modernDownload = require('./modern-download.js');
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
|
|
@@ -16,4 +17,5 @@ exports.getImageKey = utils.getImageKey;
|
|
|
16
17
|
exports.isSmallImage = utils.isSmallImage;
|
|
17
18
|
exports.isVideo = utils.isVideo;
|
|
18
19
|
exports.TestIds = constants.TestIds;
|
|
20
|
+
exports.downloadFile = modernDownload.downloadFile;
|
|
19
21
|
//# sourceMappingURL=index.js.map
|
package/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tslib = require('tslib');
|
|
6
|
+
|
|
7
|
+
var downloadWithBlob = function (blob, fileName) {
|
|
8
|
+
var url = URL.createObjectURL(blob);
|
|
9
|
+
var link = document.createElement('a');
|
|
10
|
+
link.href = url;
|
|
11
|
+
link.download = fileName;
|
|
12
|
+
document.body.appendChild(link);
|
|
13
|
+
link.click();
|
|
14
|
+
document.body.removeChild(link);
|
|
15
|
+
setTimeout(function () { return URL.revokeObjectURL(url); }, 100);
|
|
16
|
+
};
|
|
17
|
+
var downloadWithLink = function (url, fileName) {
|
|
18
|
+
var link = document.createElement('a');
|
|
19
|
+
link.href = url;
|
|
20
|
+
link.download = fileName;
|
|
21
|
+
link.target = '_blank';
|
|
22
|
+
link.rel = 'noopener noreferrer';
|
|
23
|
+
document.body.appendChild(link);
|
|
24
|
+
link.click();
|
|
25
|
+
document.body.removeChild(link);
|
|
26
|
+
};
|
|
27
|
+
var canUseBlobDownload = function () {
|
|
28
|
+
return typeof fetch === 'function' &&
|
|
29
|
+
typeof URL.createObjectURL === 'function' &&
|
|
30
|
+
typeof URL.revokeObjectURL === 'function';
|
|
31
|
+
};
|
|
32
|
+
var canUseFileShare = function () {
|
|
33
|
+
return typeof File === 'function' &&
|
|
34
|
+
typeof navigator !== 'undefined' &&
|
|
35
|
+
typeof navigator.share === 'function' &&
|
|
36
|
+
typeof navigator.canShare === 'function';
|
|
37
|
+
};
|
|
38
|
+
var canShareFiles = function (files) {
|
|
39
|
+
return canUseFileShare() && navigator.canShare({ files: files });
|
|
40
|
+
};
|
|
41
|
+
var getBlob = function (url) { return tslib.__awaiter(void 0, void 0, void 0, function () {
|
|
42
|
+
var response;
|
|
43
|
+
return tslib.__generator(this, function (_a) {
|
|
44
|
+
switch (_a.label) {
|
|
45
|
+
case 0: return [4 /*yield*/, fetch(url)];
|
|
46
|
+
case 1:
|
|
47
|
+
response = _a.sent();
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
throw new Error('Network error');
|
|
50
|
+
}
|
|
51
|
+
return [2 /*return*/, response.blob()];
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}); };
|
|
55
|
+
var isAbortError = function (error) {
|
|
56
|
+
return typeof DOMException !== 'undefined' &&
|
|
57
|
+
error instanceof DOMException &&
|
|
58
|
+
error.name === 'AbortError';
|
|
59
|
+
};
|
|
60
|
+
var downloadFile = function (_a) { return tslib.__awaiter(void 0, [_a], void 0, function (_b) {
|
|
61
|
+
var blob, file, error_1, blob;
|
|
62
|
+
var url = _b.url, _d = _b.fileName, fileName = _d === void 0 ? 'download' : _d, fileType = _b.fileType;
|
|
63
|
+
return tslib.__generator(this, function (_e) {
|
|
64
|
+
switch (_e.label) {
|
|
65
|
+
case 0:
|
|
66
|
+
if (!canUseBlobDownload()) {
|
|
67
|
+
downloadWithLink(url, fileName);
|
|
68
|
+
return [2 /*return*/];
|
|
69
|
+
}
|
|
70
|
+
if (!(canUseFileShare() && canShareFiles([new File([], fileName, { type: fileType })]))) return [3 /*break*/, 5];
|
|
71
|
+
_e.label = 1;
|
|
72
|
+
case 1:
|
|
73
|
+
_e.trys.push([1, 4, , 5]);
|
|
74
|
+
return [4 /*yield*/, getBlob(url)];
|
|
75
|
+
case 2:
|
|
76
|
+
blob = _e.sent();
|
|
77
|
+
file = new File([blob], fileName, { type: blob.type || fileType });
|
|
78
|
+
if (!canShareFiles([file])) {
|
|
79
|
+
downloadWithBlob(blob, fileName);
|
|
80
|
+
return [2 /*return*/];
|
|
81
|
+
}
|
|
82
|
+
return [4 /*yield*/, navigator.share({
|
|
83
|
+
files: [file],
|
|
84
|
+
title: "\u0421\u043A\u0430\u0447\u0430\u0442\u044C ".concat(fileName),
|
|
85
|
+
})];
|
|
86
|
+
case 3:
|
|
87
|
+
_e.sent();
|
|
88
|
+
return [2 /*return*/];
|
|
89
|
+
case 4:
|
|
90
|
+
error_1 = _e.sent();
|
|
91
|
+
if (isAbortError(error_1)) {
|
|
92
|
+
return [2 /*return*/];
|
|
93
|
+
}
|
|
94
|
+
downloadWithLink(url, fileName);
|
|
95
|
+
return [2 /*return*/];
|
|
96
|
+
case 5:
|
|
97
|
+
_e.trys.push([5, 7, , 8]);
|
|
98
|
+
return [4 /*yield*/, getBlob(url)];
|
|
99
|
+
case 6:
|
|
100
|
+
blob = _e.sent();
|
|
101
|
+
downloadWithBlob(blob, fileName);
|
|
102
|
+
return [3 /*break*/, 8];
|
|
103
|
+
case 7:
|
|
104
|
+
_e.sent();
|
|
105
|
+
downloadWithLink(url, fileName);
|
|
106
|
+
return [3 /*break*/, 8];
|
|
107
|
+
case 8: return [2 /*return*/];
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}); };
|
|
111
|
+
|
|
112
|
+
exports.downloadFile = downloadFile;
|
|
113
|
+
//# sourceMappingURL=modern-download.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modern-download.js","sources":["../src/utils/modern-download.ts"],"sourcesContent":["const downloadWithBlob = (blob: Blob, fileName: string): void => {\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n\n link.href = url;\n link.download = fileName;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n setTimeout(() => URL.revokeObjectURL(url), 100);\n};\n\nconst downloadWithLink = (url: string, fileName: string): void => {\n const link = document.createElement('a');\n\n link.href = url;\n link.download = fileName;\n link.target = '_blank';\n link.rel = 'noopener noreferrer';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n};\n\nconst canUseBlobDownload = (): boolean =>\n typeof fetch === 'function' &&\n typeof URL.createObjectURL === 'function' &&\n typeof URL.revokeObjectURL === 'function';\n\nconst canUseFileShare = (): boolean =>\n typeof File === 'function' &&\n typeof navigator !== 'undefined' &&\n typeof navigator.share === 'function' &&\n typeof navigator.canShare === 'function';\n\nconst canShareFiles = (files: File[]): boolean =>\n canUseFileShare() && navigator.canShare({ files });\n\nconst getBlob = async (url: string): Promise<Blob> => {\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error('Network error');\n }\n\n return response.blob();\n};\n\nconst isAbortError = (error: unknown): boolean =>\n typeof DOMException !== 'undefined' &&\n error instanceof DOMException &&\n error.name === 'AbortError';\n\nexport interface DownloadOptions {\n url: string;\n fileName?: string;\n fileType?: string;\n}\n\nexport const downloadFile = async ({\n url,\n fileName = 'download',\n fileType,\n}: DownloadOptions): Promise<void> => {\n if (!canUseBlobDownload()) {\n downloadWithLink(url, fileName);\n\n return;\n }\n\n if (canUseFileShare() && canShareFiles([new File([], fileName, { type: fileType })])) {\n try {\n const blob = await getBlob(url);\n\n const file = new File([blob], fileName, { type: blob.type || fileType });\n\n if (!canShareFiles([file])) {\n downloadWithBlob(blob, fileName);\n\n return;\n }\n\n await navigator.share({\n files: [file],\n title: `Скачать ${fileName}`,\n });\n\n return;\n } catch (error) {\n if (isAbortError(error)) {\n return;\n }\n\n downloadWithLink(url, fileName);\n\n return;\n }\n }\n\n try {\n const blob = await getBlob(url);\n\n downloadWithBlob(blob, fileName);\n } catch {\n downloadWithLink(url, fileName);\n }\n};\n"],"names":["__awaiter"],"mappings":"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"}
|