Skip to content

Commit 863c04d

Browse files
committed
feat(view): add support of yfm-files to useFilesGallery() hook
1 parent d9d8dab commit 863c04d

4 files changed

Lines changed: 64 additions & 23 deletions

File tree

demo/stories/view/gallery/markup.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,13 @@ export const galleryMarkup = `
66
77
![Dojocat](https://octodex.github.com/images/dojocat.jpg "The Dojocat")
88
9+
## Video
10+
911
[Video](https://static.videezy.com/system/resources/previews/000/013/444/original/Water_43_-_37s_-_4k_res.mp4)
12+
13+
## Files
14+
15+
{% file src="https://octodex.github.com/images/forktocat.jpg" name="Forktocat" type="image/jpeg" %}
16+
17+
{% file src="https://static.videezy.com/system/resources/previews/000/012/253/original/Water_17_-_9s_-_4k_res.mp4" name="Rings of water" type="video/mp4" %}
1018
`.trim();

src/view/hooks/useFilesGallery/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ export const supportedVideoExtensions = ['mp4', 'webm', 'ogg'];
55
export const supportedExtensions = [...supportedImageExtensions, ...supportedVideoExtensions];
66

77
export const extensionRegex = /\w+?$/;
8+
9+
export const YfmFileClassname = 'yfm-file';
10+
export const YfmFileAttrs = {
11+
Download: 'download',
12+
Type: 'type',
13+
} as const;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {YfmFileAttrs, YfmFileClassname} from './constants';
2+
3+
type LinkObject = {
4+
name?: string | null;
5+
mimetype?: string | null;
6+
type: 'image' | 'link' | 'file';
7+
link: string;
8+
};
9+
10+
export function buildLinkObject(elem: Element): LinkObject | null {
11+
let obj: LinkObject | null = null;
12+
13+
if (elem.tagName === 'IMG') {
14+
obj = {
15+
type: 'image',
16+
name: elem.getAttribute('alt'),
17+
link: elem.getAttribute('src') ?? '',
18+
};
19+
} else if (elem.tagName === 'A') {
20+
obj = {
21+
type: 'link',
22+
name: elem.getAttribute('title'),
23+
link: elem.getAttribute('href') ?? '',
24+
};
25+
26+
if (elem.classList.contains(YfmFileClassname)) {
27+
obj.type = 'file';
28+
obj.name = elem.getAttribute(YfmFileAttrs.Download);
29+
obj.mimetype = elem.getAttribute(YfmFileAttrs.Type);
30+
}
31+
}
32+
33+
return obj;
34+
}

src/view/hooks/useFilesGallery/useFilesGallery.tsx

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as React from 'react';
1+
import {useCallback} from 'react';
22

33
import {
44
type GalleryItemAction,
@@ -13,6 +13,7 @@ import {useToaster} from '@gravity-ui/uikit';
1313
import {i18n} from 'src/i18n/gallery';
1414

1515
import {extensionRegex, supportedExtensions, supportedVideoExtensions} from './constants';
16+
import {buildLinkObject} from './helpers';
1617
import type {FilesGalleryItemType, GalleryItemPropsWithUrl, UseFilesGalleryOptions} from './types';
1718

1819
export function useFilesGallery(
@@ -28,40 +29,32 @@ export function useFilesGallery(
2829
const toaster = useToaster();
2930

3031
return {
31-
openFilesGallery: React.useCallback(
32+
openFilesGallery: useCallback(
3233
(event: React.MouseEvent<HTMLDivElement>) => {
3334
if (!(event.target instanceof HTMLElement)) {
3435
return false;
3536
}
3637

37-
let fileLink = '';
38+
if (event.target.tagName === 'IMG' && event.target.closest('a')) return false;
3839

39-
if (event.target.tagName === 'IMG' && !event.target.closest('a')) {
40-
fileLink = event.target.getAttribute('src') ?? '';
41-
} else if (event.target.tagName === 'A') {
42-
fileLink = event.target.getAttribute('href') ?? '';
43-
}
40+
const targetFile = buildLinkObject(event.target);
4441

45-
if (!fileLink) {
46-
return false;
47-
}
42+
if (!targetFile || !targetFile.link) return false;
4843

4944
const filesFromContent = [
5045
...(event.currentTarget?.querySelectorAll('img,a') ?? []),
5146
].reduce<GalleryItemPropsWithUrl[]>((result, element) => {
52-
const isImage = element.tagName === 'IMG';
53-
const link = isImage
54-
? element.getAttribute('src')
55-
: element.getAttribute('href');
47+
const linkObj = buildLinkObject(element);
5648

57-
if (link && !customFiles?.some((item) => item.url === link)) {
58-
const extension = link.match(extensionRegex)?.[0] || '';
49+
if (linkObj?.link && !customFiles?.some((item) => item.url === linkObj.link)) {
50+
const extension =
51+
linkObj.mimetype?.match(extensionRegex)?.[0] ||
52+
linkObj.link.match(extensionRegex)?.[0] ||
53+
'';
5954

60-
if (isImage || supportedExtensions.includes(extension)) {
61-
const name =
62-
(isImage
63-
? element.getAttribute('alt')
64-
: element.getAttribute('title')) || '';
55+
if (linkObj.type === 'image' || supportedExtensions.includes(extension)) {
56+
const link = linkObj.link;
57+
const name = linkObj.name || '';
6558

6659
const filesGalleryItemType: FilesGalleryItemType =
6760
supportedVideoExtensions.includes(extension) ? 'video' : 'image';
@@ -127,7 +120,7 @@ export function useFilesGallery(
127120

128121
const files = [...(customFiles ?? []), ...filesFromContent];
129122

130-
const initialItemIndex = files.findIndex((item) => item.url === fileLink);
123+
const initialItemIndex = files.findIndex((item) => item.url === targetFile.link);
131124

132125
if (initialItemIndex !== -1) {
133126
event.preventDefault();

0 commit comments

Comments
 (0)