@atlaskit/media-viewer 48.1.7 → 48.2.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/CHANGELOG.md +11 -0
- package/dist/cjs/analytics/index.js +2 -3
- package/dist/cjs/analytics/ufoExperiences.js +1 -1
- package/dist/cjs/components/media-viewer.js +13 -1
- package/dist/cjs/errorMessage.js +5 -3
- package/dist/cjs/item-viewer.js +5 -4
- package/dist/cjs/media-viewer.js +21 -17
- package/dist/cjs/navigation.js +5 -4
- package/dist/cjs/styleWrappers.js +1 -0
- package/dist/cjs/v2/header-v2.js +159 -0
- package/dist/cjs/v2/item-viewer-v2.js +322 -0
- package/dist/cjs/v2/list-v2.js +71 -0
- package/dist/cjs/v2/media-viewer-v2.js +114 -0
- package/dist/cjs/viewers/archiveSidebar/archive.js +5 -3
- package/dist/cjs/zoomControls.js +6 -4
- package/dist/es2019/analytics/index.js +2 -5
- package/dist/es2019/analytics/ufoExperiences.js +1 -1
- package/dist/es2019/components/media-viewer.js +13 -1
- package/dist/es2019/errorMessage.js +5 -3
- package/dist/es2019/item-viewer.js +5 -4
- package/dist/es2019/media-viewer.js +8 -6
- package/dist/es2019/navigation.js +5 -4
- package/dist/es2019/styleWrappers.js +1 -0
- package/dist/es2019/v2/header-v2.js +138 -0
- package/dist/es2019/v2/item-viewer-v2.js +269 -0
- package/dist/es2019/v2/list-v2.js +52 -0
- package/dist/es2019/v2/media-viewer-v2.js +95 -0
- package/dist/es2019/viewers/archiveSidebar/archive.js +4 -3
- package/dist/es2019/zoomControls.js +6 -4
- package/dist/esm/analytics/index.js +2 -3
- package/dist/esm/analytics/ufoExperiences.js +1 -1
- package/dist/esm/components/media-viewer.js +13 -1
- package/dist/esm/errorMessage.js +5 -3
- package/dist/esm/item-viewer.js +5 -4
- package/dist/esm/media-viewer.js +21 -17
- package/dist/esm/navigation.js +5 -4
- package/dist/esm/styleWrappers.js +1 -0
- package/dist/esm/v2/header-v2.js +149 -0
- package/dist/esm/v2/item-viewer-v2.js +302 -0
- package/dist/esm/v2/list-v2.js +61 -0
- package/dist/esm/v2/media-viewer-v2.js +104 -0
- package/dist/esm/viewers/archiveSidebar/archive.js +5 -3
- package/dist/esm/zoomControls.js +6 -4
- package/dist/types/analytics/index.d.ts +2 -2
- package/dist/types/v2/header-v2.d.ts +18 -0
- package/dist/types/v2/item-viewer-v2.d.ts +21 -0
- package/dist/types/v2/list-v2.d.ts +22 -0
- package/dist/types/v2/media-viewer-v2.d.ts +14 -0
- package/dist/types-ts4.5/analytics/index.d.ts +2 -2
- package/dist/types-ts4.5/v2/header-v2.d.ts +18 -0
- package/dist/types-ts4.5/v2/item-viewer-v2.d.ts +21 -0
- package/dist/types-ts4.5/v2/list-v2.d.ts +22 -0
- package/dist/types-ts4.5/v2/media-viewer-v2.d.ts +14 -0
- package/package.json +11 -4
|
@@ -64,7 +64,7 @@ export class ItemViewerBase extends React.Component {
|
|
|
64
64
|
item.whenSuccessful(fileItem => {
|
|
65
65
|
if (isFileStateItem(fileItem)) {
|
|
66
66
|
const fileAttributes = getFileAttributes(fileItem);
|
|
67
|
-
fireAnalytics(createLoadSucceededEvent(fileAttributes, this.traceContext), this.props);
|
|
67
|
+
fireAnalytics(createLoadSucceededEvent(fileAttributes, this.traceContext), this.props.createAnalyticsEvent);
|
|
68
68
|
succeedMediaFileUfoExperience({
|
|
69
69
|
fileAttributes,
|
|
70
70
|
fileStateFlags: this.fileStateFlags
|
|
@@ -80,7 +80,7 @@ export class ItemViewerBase extends React.Component {
|
|
|
80
80
|
_defineProperty(this, "onExternalImgSuccess", () => {
|
|
81
81
|
fireAnalytics(createLoadSucceededEvent({
|
|
82
82
|
fileId: 'external-image'
|
|
83
|
-
}), this.props);
|
|
83
|
+
}), this.props.createAnalyticsEvent);
|
|
84
84
|
succeedMediaFileUfoExperience({
|
|
85
85
|
fileAttributes: {
|
|
86
86
|
fileId: 'external-image'
|
|
@@ -270,7 +270,8 @@ export class ItemViewerBase extends React.Component {
|
|
|
270
270
|
init(props) {
|
|
271
271
|
const {
|
|
272
272
|
mediaClient,
|
|
273
|
-
identifier
|
|
273
|
+
identifier,
|
|
274
|
+
createAnalyticsEvent
|
|
274
275
|
} = props;
|
|
275
276
|
if (isExternalImageIdentifier(identifier)) {
|
|
276
277
|
// external images do not need to talk to our backend,
|
|
@@ -284,7 +285,7 @@ export class ItemViewerBase extends React.Component {
|
|
|
284
285
|
const {
|
|
285
286
|
id
|
|
286
287
|
} = identifier;
|
|
287
|
-
fireAnalytics(createCommencedEvent(id, this.traceContext),
|
|
288
|
+
fireAnalytics(createCommencedEvent(id, this.traceContext), createAnalyticsEvent);
|
|
288
289
|
startMediaFileUfoExperience();
|
|
289
290
|
this.subscription = mediaClient.file.getFileState(id, {
|
|
290
291
|
collectionName: identifier.collectionName
|
|
@@ -22,20 +22,22 @@ export class MediaViewerComponent extends React.Component {
|
|
|
22
22
|
isSidebarVisible: false
|
|
23
23
|
});
|
|
24
24
|
_defineProperty(this, "onShortcutClosed", () => {
|
|
25
|
-
fireAnalytics(createClosedEvent('escKey'), this.props);
|
|
26
25
|
const {
|
|
27
|
-
onClose
|
|
26
|
+
onClose,
|
|
27
|
+
createAnalyticsEvent
|
|
28
28
|
} = this.props;
|
|
29
|
+
fireAnalytics(createClosedEvent('escKey'), createAnalyticsEvent);
|
|
29
30
|
if (onClose) {
|
|
30
31
|
onClose();
|
|
31
32
|
}
|
|
32
33
|
});
|
|
33
34
|
_defineProperty(this, "onContentClose", (_e, analyticsEvent) => {
|
|
34
35
|
const {
|
|
35
|
-
onClose
|
|
36
|
+
onClose,
|
|
37
|
+
createAnalyticsEvent
|
|
36
38
|
} = this.props;
|
|
37
39
|
if (analyticsEvent && analyticsEvent.payload && analyticsEvent.payload.actionSubject === 'button') {
|
|
38
|
-
fireAnalytics(createClosedEvent('button'),
|
|
40
|
+
fireAnalytics(createClosedEvent('button'), createAnalyticsEvent);
|
|
39
41
|
}
|
|
40
42
|
if (onClose) {
|
|
41
43
|
onClose();
|
|
@@ -70,7 +72,7 @@ export class MediaViewerComponent extends React.Component {
|
|
|
70
72
|
});
|
|
71
73
|
}
|
|
72
74
|
UNSAFE_componentWillMount() {
|
|
73
|
-
fireAnalytics(createModalEvent(), this.props);
|
|
75
|
+
fireAnalytics(createModalEvent(), this.props.createAnalyticsEvent);
|
|
74
76
|
start('MediaViewer.SessionDuration');
|
|
75
77
|
}
|
|
76
78
|
get defaultSelectedItem() {
|
|
@@ -100,7 +102,7 @@ export class MediaViewerComponent extends React.Component {
|
|
|
100
102
|
"data-testid": "media-viewer-popup",
|
|
101
103
|
className: mediaViewerPopupClass
|
|
102
104
|
}, /*#__PURE__*/React.createElement(Shortcut, {
|
|
103
|
-
|
|
105
|
+
code: 'Escape',
|
|
104
106
|
handler: this.onShortcutClosed
|
|
105
107
|
}), /*#__PURE__*/React.createElement(Content, {
|
|
106
108
|
isSidebarVisible: isSidebarVisible,
|
|
@@ -18,14 +18,15 @@ export class NavigationBase extends Component {
|
|
|
18
18
|
return () => {
|
|
19
19
|
const {
|
|
20
20
|
onChange,
|
|
21
|
-
items
|
|
21
|
+
items,
|
|
22
|
+
createAnalyticsEvent
|
|
22
23
|
} = this.props;
|
|
23
24
|
const {
|
|
24
25
|
selectedIndex
|
|
25
26
|
} = this;
|
|
26
27
|
const newItem = direction === 'next' ? items[selectedIndex + 1] : items[selectedIndex - 1];
|
|
27
28
|
if (newItem) {
|
|
28
|
-
fireAnalytics(createNavigatedEvent(direction, source, newItem),
|
|
29
|
+
fireAnalytics(createNavigatedEvent(direction, source, newItem), createAnalyticsEvent);
|
|
29
30
|
onChange(newItem);
|
|
30
31
|
}
|
|
31
32
|
};
|
|
@@ -57,7 +58,7 @@ export class NavigationBase extends Component {
|
|
|
57
58
|
}, isLeftVisible ? /*#__PURE__*/React.createElement(Arrow, {
|
|
58
59
|
className: hideControlsClassName
|
|
59
60
|
}, /*#__PURE__*/React.createElement(Shortcut, {
|
|
60
|
-
|
|
61
|
+
code: 'ArrowLeft',
|
|
61
62
|
handler: prev('keyboard')
|
|
62
63
|
}), /*#__PURE__*/React.createElement(Button, {
|
|
63
64
|
testId: prevNavButtonId,
|
|
@@ -75,7 +76,7 @@ export class NavigationBase extends Component {
|
|
|
75
76
|
})) : null), /*#__PURE__*/React.createElement(RightWrapper, null, isRightVisible ? /*#__PURE__*/React.createElement(Arrow, {
|
|
76
77
|
className: hideControlsClassName
|
|
77
78
|
}, /*#__PURE__*/React.createElement(Shortcut, {
|
|
78
|
-
|
|
79
|
+
code: 'ArrowRight',
|
|
79
80
|
handler: next('keyboard')
|
|
80
81
|
}), /*#__PURE__*/React.createElement(Button, {
|
|
81
82
|
testId: nextNavButtonId,
|
|
@@ -5,6 +5,7 @@ import { forwardRef, useMemo } from 'react';
|
|
|
5
5
|
import { arrowStyles, arrowsWrapperStyles, audioCoverStyles, audioPlayerStyles, audioStyles, baselineExtendStyles, blanketStyles, closeButtonWrapperStyles, contentWrapperStyles, customAudioPlayerWrapperStyles, customVideoPlayerWrapperStyles, defaultCoverWrapperStyles, downloadButtonWrapperStyles, errorImageStyles, errorMessageWrapperStyles, formattedMessageWrapperStyles, hdIconGroupWrapperStyles, hdIconWrapperStyles, headerStyles, headerWrapperStyles, imageWrapperStyles, imgStyles, leftHeaderStyles, leftWrapperStyles, listWrapperStyles, medatadataTextWrapperStyles, metadataFileNameStyles, metadataIconWrapperStyles, metadataSubTextStyles, metadataWrapperStyles, pdfWrapperStyles, rightHeaderStyles, rightWrapperStyles, sidebarWrapperStyles, spinnerWrapperStyles, videoStyles, zoomControlsWrapperStyles, zoomLevelIndicatorStyles, zoomWrapperStyles } from './styles';
|
|
6
6
|
import { TouchScrollable } from 'react-scrolllock';
|
|
7
7
|
import { useMergeRefs } from 'use-callback-ref';
|
|
8
|
+
// We are keeping this data-testid since JIRA is still using it in their codebase to perform checks. Before removing this, we need to ensure this 'media-viewer-popup' test id is not being used anywhere else in other codebases
|
|
8
9
|
export const Blanket = ({
|
|
9
10
|
'data-testid': datatestId,
|
|
10
11
|
className,
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { isExternalImageIdentifier, isErrorFileState } from '@atlaskit/media-client';
|
|
3
|
+
import { hideControlsClassName, messages, toHumanReadableMediaSize, MediaButton } from '@atlaskit/media-ui';
|
|
4
|
+
import { getLanguageType, getExtension, isCodeViewerItem } from '@atlaskit/media-ui/codeViewer';
|
|
5
|
+
import { FormattedMessage, injectIntl } from 'react-intl-next';
|
|
6
|
+
import { Outcome } from '../domain';
|
|
7
|
+
import { Header as HeaderWrapper, LeftHeader, RightHeader, MetadataWrapper, MetadataSubText, MedatadataTextWrapper, MetadataIconWrapper, MetadataFileName, FormattedMessageWrapper } from '../styleWrappers';
|
|
8
|
+
import { ToolbarDownloadButton, DisabledToolbarDownloadButton } from '../download';
|
|
9
|
+
import { MediaFileStateError, useFileState, useMediaClient } from '@atlaskit/media-client-react';
|
|
10
|
+
import { MimeTypeIcon } from '@atlaskit/media-ui/mime-type-icon';
|
|
11
|
+
import { getFormat } from '../viewers/codeViewer/util';
|
|
12
|
+
import { MediaViewerError } from '../errors';
|
|
13
|
+
export const HeaderV2 = ({
|
|
14
|
+
isArchiveSideBarVisible = false,
|
|
15
|
+
extensions,
|
|
16
|
+
isSidebarVisible,
|
|
17
|
+
onSidebarButtonClick,
|
|
18
|
+
identifier,
|
|
19
|
+
onSetArchiveSideBarVisible
|
|
20
|
+
}) => {
|
|
21
|
+
// States
|
|
22
|
+
const [item, setItem] = useState(Outcome.pending());
|
|
23
|
+
|
|
24
|
+
// Refs and Hooks
|
|
25
|
+
const mediaClient = useMediaClient();
|
|
26
|
+
const {
|
|
27
|
+
id,
|
|
28
|
+
collectionName,
|
|
29
|
+
occurrenceKey
|
|
30
|
+
} = identifier;
|
|
31
|
+
const {
|
|
32
|
+
fileState
|
|
33
|
+
} = useFileState(id, {
|
|
34
|
+
collectionName,
|
|
35
|
+
occurrenceKey
|
|
36
|
+
});
|
|
37
|
+
const onSetArchiveSideBarVisibleRef = useRef(onSetArchiveSideBarVisible);
|
|
38
|
+
onSetArchiveSideBarVisibleRef.current = onSetArchiveSideBarVisible;
|
|
39
|
+
|
|
40
|
+
// previous values
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (isExternalImageIdentifier(identifier)) {
|
|
43
|
+
const {
|
|
44
|
+
name = identifier.dataURI
|
|
45
|
+
} = identifier;
|
|
46
|
+
|
|
47
|
+
// Simulate a processing file state to render right metadata
|
|
48
|
+
const fileState = {
|
|
49
|
+
status: 'processing',
|
|
50
|
+
id: name,
|
|
51
|
+
mediaType: 'image',
|
|
52
|
+
mimeType: 'image/',
|
|
53
|
+
name,
|
|
54
|
+
representations: {},
|
|
55
|
+
size: 0
|
|
56
|
+
};
|
|
57
|
+
setItem(Outcome.successful(fileState));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (!fileState) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (fileState.status !== 'error') {
|
|
64
|
+
var _onSetArchiveSideBarV;
|
|
65
|
+
(_onSetArchiveSideBarV = onSetArchiveSideBarVisibleRef.current) === null || _onSetArchiveSideBarV === void 0 ? void 0 : _onSetArchiveSideBarV.call(onSetArchiveSideBarVisibleRef, !isErrorFileState(fileState) && fileState.mediaType === 'archive');
|
|
66
|
+
setItem(Outcome.successful(fileState));
|
|
67
|
+
} else {
|
|
68
|
+
const error = new MediaFileStateError(fileState.id, fileState.reason, fileState.message, fileState.details);
|
|
69
|
+
setItem(Outcome.failed(new MediaViewerError('header-fetch-metadata', error)));
|
|
70
|
+
}
|
|
71
|
+
}, [fileState, identifier]);
|
|
72
|
+
const renderFileTypeText = item => {
|
|
73
|
+
// render appropriate header if its a code/email item and the feature flag is enabled
|
|
74
|
+
if (isCodeViewerItem(item.name, item.mimeType)) {
|
|
75
|
+
// gather language and extension
|
|
76
|
+
// i.e test.py would have a language of 'python' and an extension of 'py'
|
|
77
|
+
const language = getLanguageType(item.name, item.mimeType);
|
|
78
|
+
const ext = getExtension(item.name);
|
|
79
|
+
|
|
80
|
+
// specific cases for if we want a certain word translated in other languages
|
|
81
|
+
switch (ext) {
|
|
82
|
+
case 'msg':
|
|
83
|
+
return /*#__PURE__*/React.createElement(FormattedMessage, messages.email);
|
|
84
|
+
case 'txt':
|
|
85
|
+
return /*#__PURE__*/React.createElement(FormattedMessage, messages.text);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// no need for translations in other languages
|
|
89
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, getFormat(language || 'unknown', ext));
|
|
90
|
+
}
|
|
91
|
+
const {
|
|
92
|
+
mediaType
|
|
93
|
+
} = item;
|
|
94
|
+
const mediaTypeTranslationMap = {
|
|
95
|
+
doc: messages.document,
|
|
96
|
+
audio: messages.audio,
|
|
97
|
+
video: messages.video,
|
|
98
|
+
image: messages.image,
|
|
99
|
+
archive: messages.archive,
|
|
100
|
+
unknown: messages.unknown
|
|
101
|
+
};
|
|
102
|
+
const message = mediaTypeTranslationMap[mediaType || 'unknown'];
|
|
103
|
+
|
|
104
|
+
// Defaulting to unknown again since backend has more mediaTypes than the current supported ones
|
|
105
|
+
return /*#__PURE__*/React.createElement(FormattedMessage, message || messages.unknown);
|
|
106
|
+
};
|
|
107
|
+
return /*#__PURE__*/React.createElement(HeaderWrapper, {
|
|
108
|
+
isArchiveSideBarVisible: isArchiveSideBarVisible,
|
|
109
|
+
className: hideControlsClassName
|
|
110
|
+
}, /*#__PURE__*/React.createElement(LeftHeader, null, item.match({
|
|
111
|
+
successful: item => !isErrorFileState(item) && /*#__PURE__*/React.createElement(MetadataWrapper, null, /*#__PURE__*/React.createElement(MetadataIconWrapper, null, /*#__PURE__*/React.createElement(MimeTypeIcon, {
|
|
112
|
+
testId: 'media-viewer-file-type-icon',
|
|
113
|
+
mediaType: item.mediaType,
|
|
114
|
+
mimeType: item.mimeType,
|
|
115
|
+
name: item.name
|
|
116
|
+
})), /*#__PURE__*/React.createElement(MedatadataTextWrapper, null, /*#__PURE__*/React.createElement(MetadataFileName, {
|
|
117
|
+
"data-testid": "media-viewer-file-name"
|
|
118
|
+
}, item.name || /*#__PURE__*/React.createElement(FormattedMessage, messages.unknown)), /*#__PURE__*/React.createElement(MetadataSubText, {
|
|
119
|
+
"data-testid": "media-viewer-file-metadata-text"
|
|
120
|
+
}, /*#__PURE__*/React.createElement(FormattedMessageWrapper, null, renderFileTypeText(item)), item.size ? ' · ' + toHumanReadableMediaSize(item.size) : ''))),
|
|
121
|
+
pending: () => null,
|
|
122
|
+
failed: () => null
|
|
123
|
+
})), /*#__PURE__*/React.createElement(RightHeader, null, (extensions === null || extensions === void 0 ? void 0 : extensions.sidebar) && /*#__PURE__*/React.createElement(MediaButton, {
|
|
124
|
+
isSelected: isSidebarVisible,
|
|
125
|
+
testId: "media-viewer-sidebar-button",
|
|
126
|
+
onClick: onSidebarButtonClick,
|
|
127
|
+
iconBefore: extensions.sidebar.icon
|
|
128
|
+
}), item.match({
|
|
129
|
+
pending: () => DisabledToolbarDownloadButton,
|
|
130
|
+
failed: () => DisabledToolbarDownloadButton,
|
|
131
|
+
successful: item => /*#__PURE__*/React.createElement(ToolbarDownloadButton, {
|
|
132
|
+
state: item,
|
|
133
|
+
identifier: identifier,
|
|
134
|
+
mediaClient: mediaClient
|
|
135
|
+
})
|
|
136
|
+
})));
|
|
137
|
+
};
|
|
138
|
+
export default injectIntl(HeaderV2);
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React, { useCallback, useEffect, useState, useRef } from 'react';
|
|
3
|
+
import Loadable from 'react-loadable';
|
|
4
|
+
import { isExternalImageIdentifier, isFileIdentifier } from '@atlaskit/media-client';
|
|
5
|
+
import { FormattedMessage } from 'react-intl-next';
|
|
6
|
+
import { messages } from '@atlaskit/media-ui';
|
|
7
|
+
import { isCodeViewerItem } from '@atlaskit/media-ui/codeViewer';
|
|
8
|
+
import { useFileState, useMediaClient, MediaFileStateError } from '@atlaskit/media-client-react';
|
|
9
|
+
import { Outcome } from '../domain';
|
|
10
|
+
import { Spinner } from '../loading';
|
|
11
|
+
import ErrorMessage from '../errorMessage';
|
|
12
|
+
import { MediaViewerError } from '../errors';
|
|
13
|
+
import { ErrorViewDownloadButton } from '../download';
|
|
14
|
+
import { withAnalyticsEvents } from '@atlaskit/analytics-next';
|
|
15
|
+
import { createCommencedEvent } from '../analytics/events/operational/commenced';
|
|
16
|
+
import { createLoadSucceededEvent } from '../analytics/events/operational/loadSucceeded';
|
|
17
|
+
import { fireAnalytics, getFileAttributes } from '../analytics';
|
|
18
|
+
import { InteractiveImg } from '../viewers/image/interactive-img';
|
|
19
|
+
import ArchiveViewerLoader from '../viewers/archiveSidebar/archiveViewerLoader';
|
|
20
|
+
import { getRandomHex } from '@atlaskit/media-common';
|
|
21
|
+
import { startMediaFileUfoExperience, succeedMediaFileUfoExperience } from '../analytics/ufoExperiences';
|
|
22
|
+
const ImageViewer = Loadable({
|
|
23
|
+
loader: () => import( /* webpackChunkName: "@atlaskit-internal_imageViewer" */'../viewers/image').then(mod => mod.ImageViewer),
|
|
24
|
+
loading: () => /*#__PURE__*/React.createElement(Spinner, null)
|
|
25
|
+
});
|
|
26
|
+
const VideoViewer = Loadable({
|
|
27
|
+
loader: () => import( /* webpackChunkName: "@atlaskit-internal_videoViewer" */'../viewers/video').then(mod => mod.VideoViewer),
|
|
28
|
+
loading: () => /*#__PURE__*/React.createElement(Spinner, null)
|
|
29
|
+
});
|
|
30
|
+
const AudioViewer = Loadable({
|
|
31
|
+
loader: () => import( /* webpackChunkName: "@atlaskit-internal_audioViewer" */'../viewers/audio').then(mod => mod.AudioViewer),
|
|
32
|
+
loading: () => /*#__PURE__*/React.createElement(Spinner, null)
|
|
33
|
+
});
|
|
34
|
+
const DocViewer = Loadable({
|
|
35
|
+
loader: () => import( /* webpackChunkName: "@atlaskit-internal_docViewer" */'../viewers/doc').then(mod => mod.DocViewer),
|
|
36
|
+
loading: () => /*#__PURE__*/React.createElement(Spinner, null)
|
|
37
|
+
});
|
|
38
|
+
const CodeViewer = Loadable({
|
|
39
|
+
loader: () => import( /* webpackChunkName: "@atlaskit-internal_codeViewer" */'../viewers/codeViewer').then(mod => mod.CodeViewer),
|
|
40
|
+
loading: () => /*#__PURE__*/React.createElement(Spinner, null)
|
|
41
|
+
});
|
|
42
|
+
// Consts
|
|
43
|
+
export const isExternalImageItem = fileItem => fileItem === 'external-image';
|
|
44
|
+
export const isFileStateItem = fileItem => !isExternalImageItem(fileItem);
|
|
45
|
+
export const MAX_FILE_SIZE_SUPPORTED_BY_CODEVIEWER = 10 * 1024 * 1024;
|
|
46
|
+
export const ItemViewerV2Base = ({
|
|
47
|
+
identifier,
|
|
48
|
+
showControls,
|
|
49
|
+
onClose,
|
|
50
|
+
previewCount,
|
|
51
|
+
contextId,
|
|
52
|
+
createAnalyticsEvent
|
|
53
|
+
}) => {
|
|
54
|
+
// States and Refs
|
|
55
|
+
const [item, setItem] = useState(Outcome.pending());
|
|
56
|
+
const traceContext = useRef({
|
|
57
|
+
traceId: getRandomHex(8)
|
|
58
|
+
});
|
|
59
|
+
const fileStateFlagsRef = useRef({
|
|
60
|
+
wasStatusUploading: false,
|
|
61
|
+
wasStatusProcessing: false
|
|
62
|
+
});
|
|
63
|
+
const createAnalyticsEventRef = useRef(createAnalyticsEvent);
|
|
64
|
+
createAnalyticsEventRef.current = createAnalyticsEvent;
|
|
65
|
+
|
|
66
|
+
// Hooks
|
|
67
|
+
const mediaClient = useMediaClient();
|
|
68
|
+
const {
|
|
69
|
+
fileState
|
|
70
|
+
} = useFileState(isExternalImageIdentifier(identifier) ? '' : identifier.id, {
|
|
71
|
+
collectionName: isExternalImageIdentifier(identifier) ? '' : identifier.collectionName,
|
|
72
|
+
skipRemote: isExternalImageIdentifier(identifier)
|
|
73
|
+
});
|
|
74
|
+
const renderDownloadButton = useCallback((fileState, error) => {
|
|
75
|
+
const collectionName = isFileIdentifier(identifier) ? identifier.collectionName : undefined;
|
|
76
|
+
return /*#__PURE__*/React.createElement(ErrorViewDownloadButton, {
|
|
77
|
+
fileState: fileState,
|
|
78
|
+
mediaClient: mediaClient,
|
|
79
|
+
error: error,
|
|
80
|
+
collectionName: collectionName
|
|
81
|
+
});
|
|
82
|
+
}, [mediaClient, identifier]);
|
|
83
|
+
|
|
84
|
+
// Did mount
|
|
85
|
+
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (isExternalImageIdentifier(identifier)) {
|
|
88
|
+
// external images do not need to talk to our backend,
|
|
89
|
+
// so therefore no need for media-client subscriptions.
|
|
90
|
+
// just set a successful outcome of type "external-image".
|
|
91
|
+
setItem(Outcome.successful('external-image'));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
fireAnalytics(createCommencedEvent(identifier === null || identifier === void 0 ? void 0 : identifier.id, traceContext.current), createAnalyticsEventRef.current);
|
|
95
|
+
startMediaFileUfoExperience();
|
|
96
|
+
|
|
97
|
+
// File Subscription
|
|
98
|
+
|
|
99
|
+
if (fileState) {
|
|
100
|
+
const {
|
|
101
|
+
status
|
|
102
|
+
} = fileState;
|
|
103
|
+
if (fileState.status !== 'error') {
|
|
104
|
+
// updateFileStateFlag
|
|
105
|
+
|
|
106
|
+
if (status === 'processing') {
|
|
107
|
+
fileStateFlagsRef.current.wasStatusProcessing = true;
|
|
108
|
+
} else if (status === 'uploading') {
|
|
109
|
+
fileStateFlagsRef.current.wasStatusUploading = true;
|
|
110
|
+
}
|
|
111
|
+
setItem(Outcome.successful(fileState));
|
|
112
|
+
} else {
|
|
113
|
+
const e = new MediaFileStateError(fileState.id, fileState.reason, fileState.message, fileState.details);
|
|
114
|
+
setItem(Outcome.failed(new MediaViewerError('itemviewer-fetch-metadata', e)));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}, [fileState, identifier]);
|
|
118
|
+
const onSuccess = useCallback(() => {
|
|
119
|
+
item.whenSuccessful(fileItem => {
|
|
120
|
+
if (isFileStateItem(fileItem)) {
|
|
121
|
+
const fileAttributes = getFileAttributes(fileItem);
|
|
122
|
+
fireAnalytics(createLoadSucceededEvent(fileAttributes, traceContext.current), createAnalyticsEventRef.current);
|
|
123
|
+
succeedMediaFileUfoExperience({
|
|
124
|
+
fileAttributes,
|
|
125
|
+
fileStateFlags: fileStateFlagsRef.current
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}, [item]);
|
|
130
|
+
const onLoadFail = useCallback(mediaViewerError => {
|
|
131
|
+
setItem(Outcome.failed(mediaViewerError));
|
|
132
|
+
}, []);
|
|
133
|
+
const renderError = useCallback((error, fileItem) => {
|
|
134
|
+
if (fileItem) {
|
|
135
|
+
let fileState;
|
|
136
|
+
if (fileItem === 'external-image') {
|
|
137
|
+
// external image error outcome
|
|
138
|
+
fileState = {
|
|
139
|
+
id: 'external-image',
|
|
140
|
+
status: 'error'
|
|
141
|
+
};
|
|
142
|
+
} else {
|
|
143
|
+
// FileState error outcome
|
|
144
|
+
fileState = fileItem;
|
|
145
|
+
}
|
|
146
|
+
return /*#__PURE__*/React.createElement(ErrorMessage, {
|
|
147
|
+
fileId: isFileIdentifier(identifier) ? identifier.id : 'undefined',
|
|
148
|
+
error: error,
|
|
149
|
+
fileState: fileState,
|
|
150
|
+
fileStateFlags: fileStateFlagsRef.current,
|
|
151
|
+
traceContext: traceContext.current
|
|
152
|
+
}, /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement(FormattedMessage, messages.try_downloading_file)), renderDownloadButton(fileState, error));
|
|
153
|
+
} else {
|
|
154
|
+
return /*#__PURE__*/React.createElement(ErrorMessage, {
|
|
155
|
+
fileId: isFileIdentifier(identifier) ? identifier.id : 'undefined',
|
|
156
|
+
error: error,
|
|
157
|
+
fileStateFlags: fileStateFlagsRef.current
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}, [identifier, renderDownloadButton, traceContext]);
|
|
161
|
+
return item.match({
|
|
162
|
+
successful: fileItem => {
|
|
163
|
+
if (fileItem === 'external-image') {
|
|
164
|
+
// render an external image
|
|
165
|
+
const {
|
|
166
|
+
dataURI
|
|
167
|
+
} = identifier;
|
|
168
|
+
return /*#__PURE__*/React.createElement(InteractiveImg, {
|
|
169
|
+
src: dataURI,
|
|
170
|
+
onLoad: () => {
|
|
171
|
+
fireAnalytics(createLoadSucceededEvent({
|
|
172
|
+
fileId: 'external-image'
|
|
173
|
+
}), createAnalyticsEventRef.current);
|
|
174
|
+
succeedMediaFileUfoExperience({
|
|
175
|
+
fileAttributes: {
|
|
176
|
+
fileId: 'external-image'
|
|
177
|
+
},
|
|
178
|
+
fileStateFlags: fileStateFlagsRef.current
|
|
179
|
+
});
|
|
180
|
+
},
|
|
181
|
+
onError: () => {
|
|
182
|
+
setItem(Outcome.failed(new MediaViewerError('imageviewer-external-onerror')));
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
} else {
|
|
186
|
+
// render a FileState fetched through media-client
|
|
187
|
+
switch (fileItem.status) {
|
|
188
|
+
case 'processed':
|
|
189
|
+
case 'uploading':
|
|
190
|
+
case 'processing':
|
|
191
|
+
// TODO: renderItem
|
|
192
|
+
const collectionName = isFileIdentifier(identifier) ? identifier.collectionName : undefined;
|
|
193
|
+
const viewerProps = {
|
|
194
|
+
mediaClient,
|
|
195
|
+
item: fileItem,
|
|
196
|
+
collectionName,
|
|
197
|
+
onClose,
|
|
198
|
+
previewCount
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// TODO: fix all of the item errors
|
|
202
|
+
|
|
203
|
+
if (isCodeViewerItem(fileItem.name, fileItem.mimeType)) {
|
|
204
|
+
//Render error message if code file has size over 10MB.
|
|
205
|
+
//Required by https://product-fabric.atlassian.net/browse/MEX-1788
|
|
206
|
+
if (fileItem.size > MAX_FILE_SIZE_SUPPORTED_BY_CODEVIEWER) {
|
|
207
|
+
return renderError(new MediaViewerError('codeviewer-file-size-exceeds'), fileItem);
|
|
208
|
+
}
|
|
209
|
+
return /*#__PURE__*/React.createElement(CodeViewer, _extends({
|
|
210
|
+
onSuccess: onSuccess,
|
|
211
|
+
onError: onLoadFail
|
|
212
|
+
}, viewerProps));
|
|
213
|
+
}
|
|
214
|
+
const {
|
|
215
|
+
mediaType
|
|
216
|
+
} = fileItem;
|
|
217
|
+
switch (mediaType) {
|
|
218
|
+
case 'image':
|
|
219
|
+
return /*#__PURE__*/React.createElement(ImageViewer, _extends({
|
|
220
|
+
onLoad: onSuccess,
|
|
221
|
+
onError: onLoadFail,
|
|
222
|
+
contextId: contextId,
|
|
223
|
+
traceContext: traceContext.current
|
|
224
|
+
}, viewerProps));
|
|
225
|
+
case 'audio':
|
|
226
|
+
return /*#__PURE__*/React.createElement(AudioViewer, _extends({
|
|
227
|
+
showControls: showControls,
|
|
228
|
+
onCanPlay: onSuccess,
|
|
229
|
+
onError: onLoadFail
|
|
230
|
+
}, viewerProps));
|
|
231
|
+
case 'video':
|
|
232
|
+
return /*#__PURE__*/React.createElement(VideoViewer, _extends({
|
|
233
|
+
showControls: showControls,
|
|
234
|
+
onCanPlay: onSuccess,
|
|
235
|
+
onError: onLoadFail
|
|
236
|
+
}, viewerProps));
|
|
237
|
+
case 'doc':
|
|
238
|
+
return /*#__PURE__*/React.createElement(DocViewer, _extends({
|
|
239
|
+
onSuccess: onSuccess,
|
|
240
|
+
onError: onLoadFail
|
|
241
|
+
}, viewerProps));
|
|
242
|
+
case 'archive':
|
|
243
|
+
return /*#__PURE__*/React.createElement(ArchiveViewerLoader, _extends({
|
|
244
|
+
onSuccess: onSuccess,
|
|
245
|
+
onError: onLoadFail
|
|
246
|
+
}, viewerProps));
|
|
247
|
+
}
|
|
248
|
+
return renderError(new MediaViewerError('unsupported'), fileItem);
|
|
249
|
+
case 'failed-processing':
|
|
250
|
+
return renderError(new MediaViewerError('itemviewer-file-failed-processing-status'), fileItem);
|
|
251
|
+
case 'error':
|
|
252
|
+
return renderError(new MediaViewerError('itemviewer-file-error-status'), fileItem);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
pending: () => /*#__PURE__*/React.createElement(Spinner, null),
|
|
257
|
+
failed: error => renderError(error, item.data)
|
|
258
|
+
});
|
|
259
|
+
};
|
|
260
|
+
const ViewerWithKey = props => {
|
|
261
|
+
const {
|
|
262
|
+
identifier
|
|
263
|
+
} = props;
|
|
264
|
+
const key = isFileIdentifier(identifier) ? identifier.id : identifier.dataURI;
|
|
265
|
+
return /*#__PURE__*/React.createElement(ItemViewerV2Base, _extends({}, props, {
|
|
266
|
+
key: key
|
|
267
|
+
}));
|
|
268
|
+
};
|
|
269
|
+
export const ItemViewerV2 = withAnalyticsEvents()(ViewerWithKey);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { hideControlsClassName } from '@atlaskit/media-ui';
|
|
3
|
+
import { ItemViewerV2 } from './item-viewer-v2';
|
|
4
|
+
import { HeaderWrapper, ListWrapper } from '../styleWrappers';
|
|
5
|
+
import { Navigation } from '../navigation';
|
|
6
|
+
import HeaderV2 from './header-v2';
|
|
7
|
+
export const ListV2 = ({
|
|
8
|
+
defaultSelectedItem,
|
|
9
|
+
onClose,
|
|
10
|
+
showControls,
|
|
11
|
+
extensions,
|
|
12
|
+
onSidebarButtonClick,
|
|
13
|
+
contextId,
|
|
14
|
+
featureFlags,
|
|
15
|
+
isSidebarVisible,
|
|
16
|
+
onNavigationChange,
|
|
17
|
+
items
|
|
18
|
+
}) => {
|
|
19
|
+
const [selectedItem, setSelectedItem] = useState(defaultSelectedItem);
|
|
20
|
+
const [previewCount, setPreviewCount] = useState(0);
|
|
21
|
+
const [isArchiveSideBarVisible, setIsArchiveSideBarVisible] = useState(false);
|
|
22
|
+
return /*#__PURE__*/React.createElement(ListWrapper, null, /*#__PURE__*/React.createElement(HeaderWrapper, {
|
|
23
|
+
className: hideControlsClassName,
|
|
24
|
+
isArchiveSideBarVisible: isArchiveSideBarVisible
|
|
25
|
+
}, /*#__PURE__*/React.createElement(HeaderV2, {
|
|
26
|
+
identifier: selectedItem,
|
|
27
|
+
onClose: onClose,
|
|
28
|
+
extensions: extensions,
|
|
29
|
+
onSidebarButtonClick: onSidebarButtonClick,
|
|
30
|
+
isSidebarVisible: isSidebarVisible,
|
|
31
|
+
isArchiveSideBarVisible: isArchiveSideBarVisible,
|
|
32
|
+
featureFlags: featureFlags,
|
|
33
|
+
onSetArchiveSideBarVisible: setIsArchiveSideBarVisible
|
|
34
|
+
})), /*#__PURE__*/React.createElement(ItemViewerV2, {
|
|
35
|
+
identifier: selectedItem,
|
|
36
|
+
showControls: showControls,
|
|
37
|
+
onClose: onClose,
|
|
38
|
+
previewCount: previewCount,
|
|
39
|
+
contextId: contextId,
|
|
40
|
+
featureFlags: featureFlags
|
|
41
|
+
}), /*#__PURE__*/React.createElement(Navigation, {
|
|
42
|
+
items: items,
|
|
43
|
+
selectedItem: selectedItem,
|
|
44
|
+
onChange: selectedItem => {
|
|
45
|
+
onNavigationChange === null || onNavigationChange === void 0 ? void 0 : onNavigationChange(selectedItem);
|
|
46
|
+
showControls === null || showControls === void 0 ? void 0 : showControls();
|
|
47
|
+
setSelectedItem(selectedItem);
|
|
48
|
+
setPreviewCount(previewCount + 1);
|
|
49
|
+
},
|
|
50
|
+
isArchiveSideBarVisible: isArchiveSideBarVisible
|
|
51
|
+
}));
|
|
52
|
+
};
|