@atlaskit/media-client 20.0.0 → 20.0.2
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 +13 -0
- package/dist/cjs/client/collection-fetcher.js +4 -44
- package/dist/cjs/client/file-fetcher/error.js +3 -19
- package/dist/cjs/client/file-fetcher/index.js +152 -167
- package/dist/cjs/client/media-client.js +3 -27
- package/dist/cjs/client/media-store/error.js +1 -17
- package/dist/cjs/client/media-store/index.js +13 -103
- package/dist/cjs/client/media-store/resolveAuth.js +2 -23
- package/dist/cjs/client/mobile-upload.js +9 -22
- package/dist/cjs/client/stargate-client.js +0 -12
- package/dist/cjs/constants.js +0 -3
- package/dist/cjs/file-streams-cache.js +0 -11
- package/dist/cjs/globalMediaEventEmitter.js +0 -3
- package/dist/cjs/identifier.js +0 -8
- package/dist/cjs/index.js +0 -38
- package/dist/cjs/models/artifacts.js +0 -4
- package/dist/cjs/models/auth-headers.js +0 -2
- package/dist/cjs/models/auth-query-parameters.js +0 -2
- package/dist/cjs/models/errors/helpers.js +0 -2
- package/dist/cjs/models/errors/index.js +4 -20
- package/dist/cjs/models/file-state.js +10 -36
- package/dist/cjs/models/media.js +2 -8
- package/dist/cjs/upload-controller.js +0 -6
- package/dist/cjs/uploader/calculateChunkSize.js +1 -10
- package/dist/cjs/uploader/error.js +3 -19
- package/dist/cjs/uploader/index.js +3 -43
- package/dist/cjs/utils/checkWebpSupport.js +3 -7
- package/dist/cjs/utils/convertBase64ToBlob.js +0 -5
- package/dist/cjs/utils/createFileDataLoader.js +4 -28
- package/dist/cjs/utils/createMediaSubject.js +0 -4
- package/dist/cjs/utils/detectEmptyFile.js +8 -15
- package/dist/cjs/utils/getDimensionsFromBlob.js +0 -14
- package/dist/cjs/utils/getImageDimensionsFromBlob.js +0 -4
- package/dist/cjs/utils/getMediaTypeFromUploadableFile.js +0 -3
- package/dist/cjs/utils/getVideoDimensionsFromBlob.js +2 -8
- package/dist/cjs/utils/hashing/hasherCreator.js +0 -20
- package/dist/cjs/utils/hashing/simpleHasher.js +0 -12
- package/dist/cjs/utils/hashing/workerHasher.js +3 -24
- package/dist/cjs/utils/imageResizeModeToFileImageMode.js +0 -2
- package/dist/cjs/utils/isImageRemote.js +0 -5
- package/dist/cjs/utils/mediaSubscribable/fromObservable.js +2 -4
- package/dist/cjs/utils/mediaSubscribable/index.js +0 -2
- package/dist/cjs/utils/mediaSubscribable/toPromise.js +1 -3
- package/dist/cjs/utils/mobileUpload/error.js +3 -19
- package/dist/cjs/utils/mobileUpload/helpers.js +2 -26
- package/dist/cjs/utils/mobileUpload/index.js +0 -4
- package/dist/cjs/utils/mobileUpload/servicesCache.js +0 -2
- package/dist/cjs/utils/mobileUpload/stateMachine/index.js +0 -22
- package/dist/cjs/utils/mobileUpload/stateMachine/states/processing.js +0 -2
- package/dist/cjs/utils/mobileUpload/stateMachine/states/uploading.js +0 -7
- package/dist/cjs/utils/overrideMediaTypeIfUnknown.js +0 -4
- package/dist/cjs/utils/polling/errors.js +1 -17
- package/dist/cjs/utils/polling/index.js +1 -30
- package/dist/cjs/utils/request/errors.js +8 -24
- package/dist/cjs/utils/request/helpers.js +19 -103
- package/dist/cjs/utils/request/index.js +15 -26
- package/dist/cjs/utils/safeUnsubscribe.js +0 -2
- package/dist/cjs/utils/setTimeoutPromise.js +0 -4
- package/dist/cjs/utils/shouldFetchRemoteFileStates.js +0 -21
- package/dist/cjs/utils/url.js +4 -27
- package/dist/cjs/utils/with-media-client-hoc.js +12 -28
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/client/collection-fetcher.js +6 -18
- package/dist/es2019/client/file-fetcher/error.js +0 -2
- package/dist/es2019/client/file-fetcher/index.js +138 -70
- package/dist/es2019/client/media-client.js +4 -14
- package/dist/es2019/client/media-store/error.js +0 -2
- package/dist/es2019/client/media-store/index.js +37 -52
- package/dist/es2019/client/media-store/resolveAuth.js +1 -5
- package/dist/es2019/client/mobile-upload.js +0 -8
- package/dist/es2019/client/stargate-client.js +0 -3
- package/dist/es2019/constants.js +0 -1
- package/dist/es2019/file-streams-cache.js +0 -11
- package/dist/es2019/globalMediaEventEmitter.js +0 -4
- package/dist/es2019/index.js +4 -11
- package/dist/es2019/models/artifacts.js +0 -2
- package/dist/es2019/models/errors/index.js +5 -4
- package/dist/es2019/models/file-state.js +6 -7
- package/dist/es2019/models/media.js +2 -3
- package/dist/es2019/upload-controller.js +0 -3
- package/dist/es2019/uploader/calculateChunkSize.js +1 -4
- package/dist/es2019/uploader/error.js +0 -2
- package/dist/es2019/uploader/index.js +0 -13
- package/dist/es2019/utils/checkWebpSupport.js +3 -4
- package/dist/es2019/utils/convertBase64ToBlob.js +0 -2
- package/dist/es2019/utils/createFileDataLoader.js +6 -9
- package/dist/es2019/utils/createMediaSubject.js +0 -2
- package/dist/es2019/utils/detectEmptyFile.js +1 -5
- package/dist/es2019/utils/getDimensionsFromBlob.js +0 -3
- package/dist/es2019/utils/getImageDimensionsFromBlob.js +0 -2
- package/dist/es2019/utils/getVideoDimensionsFromBlob.js +2 -1
- package/dist/es2019/utils/hashing/hasherCreator.js +0 -2
- package/dist/es2019/utils/hashing/simpleHasher.js +0 -3
- package/dist/es2019/utils/hashing/workerHasher.js +1 -16
- package/dist/es2019/utils/isImageRemote.js +0 -2
- package/dist/es2019/utils/mediaSubscribable/fromObservable.js +2 -1
- package/dist/es2019/utils/mediaSubscribable/toPromise.js +1 -1
- package/dist/es2019/utils/mobileUpload/error.js +0 -2
- package/dist/es2019/utils/mobileUpload/helpers.js +2 -7
- package/dist/es2019/utils/mobileUpload/stateMachine/index.js +0 -2
- package/dist/es2019/utils/mobileUpload/stateMachine/states/uploading.js +2 -1
- package/dist/es2019/utils/overrideMediaTypeIfUnknown.js +0 -1
- package/dist/es2019/utils/polling/errors.js +0 -2
- package/dist/es2019/utils/polling/index.js +3 -20
- package/dist/es2019/utils/request/errors.js +0 -2
- package/dist/es2019/utils/request/helpers.js +24 -35
- package/dist/es2019/utils/request/index.js +2 -2
- package/dist/es2019/utils/shouldFetchRemoteFileStates.js +1 -5
- package/dist/es2019/utils/url.js +6 -14
- package/dist/es2019/utils/with-media-client-hoc.js +10 -7
- package/dist/es2019/version.json +1 -1
- package/dist/esm/client/collection-fetcher.js +4 -34
- package/dist/esm/client/file-fetcher/error.js +3 -12
- package/dist/esm/client/file-fetcher/index.js +154 -137
- package/dist/esm/client/media-client.js +4 -17
- package/dist/esm/client/media-store/error.js +1 -10
- package/dist/esm/client/media-store/index.js +13 -89
- package/dist/esm/client/media-store/resolveAuth.js +2 -13
- package/dist/esm/client/mobile-upload.js +9 -15
- package/dist/esm/client/stargate-client.js +0 -7
- package/dist/esm/constants.js +0 -1
- package/dist/esm/file-streams-cache.js +0 -6
- package/dist/esm/globalMediaEventEmitter.js +0 -1
- package/dist/esm/index.js +4 -11
- package/dist/esm/models/artifacts.js +0 -2
- package/dist/esm/models/errors/index.js +5 -12
- package/dist/esm/models/file-state.js +10 -17
- package/dist/esm/models/media.js +2 -3
- package/dist/esm/upload-controller.js +0 -2
- package/dist/esm/uploader/calculateChunkSize.js +1 -4
- package/dist/esm/uploader/error.js +3 -12
- package/dist/esm/uploader/index.js +3 -32
- package/dist/esm/utils/checkWebpSupport.js +3 -4
- package/dist/esm/utils/convertBase64ToBlob.js +0 -3
- package/dist/esm/utils/createFileDataLoader.js +4 -18
- package/dist/esm/utils/createMediaSubject.js +0 -2
- package/dist/esm/utils/detectEmptyFile.js +8 -12
- package/dist/esm/utils/getDimensionsFromBlob.js +0 -7
- package/dist/esm/utils/getImageDimensionsFromBlob.js +0 -2
- package/dist/esm/utils/getVideoDimensionsFromBlob.js +2 -3
- package/dist/esm/utils/hashing/hasherCreator.js +0 -9
- package/dist/esm/utils/hashing/simpleHasher.js +0 -4
- package/dist/esm/utils/hashing/workerHasher.js +3 -18
- package/dist/esm/utils/isImageRemote.js +0 -3
- package/dist/esm/utils/mediaSubscribable/fromObservable.js +2 -1
- package/dist/esm/utils/mediaSubscribable/toPromise.js +1 -1
- package/dist/esm/utils/mobileUpload/error.js +3 -12
- package/dist/esm/utils/mobileUpload/helpers.js +2 -11
- package/dist/esm/utils/mobileUpload/stateMachine/index.js +0 -6
- package/dist/esm/utils/mobileUpload/stateMachine/states/uploading.js +0 -3
- package/dist/esm/utils/overrideMediaTypeIfUnknown.js +0 -1
- package/dist/esm/utils/polling/errors.js +1 -10
- package/dist/esm/utils/polling/index.js +1 -27
- package/dist/esm/utils/request/errors.js +8 -17
- package/dist/esm/utils/request/helpers.js +22 -76
- package/dist/esm/utils/request/index.js +15 -20
- package/dist/esm/utils/shouldFetchRemoteFileStates.js +1 -15
- package/dist/esm/utils/url.js +4 -18
- package/dist/esm/utils/with-media-client-hoc.js +12 -17
- package/dist/esm/version.json +1 -1
- package/dist/types/client/file-fetcher/index.d.ts +6 -2
- package/package.json +8 -6
- package/report.api.md +4 -1
|
@@ -3,9 +3,9 @@ import { Subscription } from 'rxjs/Subscription';
|
|
|
3
3
|
import { of } from 'rxjs/observable/of';
|
|
4
4
|
import { map } from 'rxjs/operators/map';
|
|
5
5
|
import { concatMap } from 'rxjs/operators/concatMap';
|
|
6
|
-
import uuid from 'uuid/v4';
|
|
6
|
+
import uuid from 'uuid/v4';
|
|
7
|
+
// import setimmediate to temporary fix dataloader 2.0.0 bug
|
|
7
8
|
// @see https://github.com/graphql/dataloader/issues/249
|
|
8
|
-
|
|
9
9
|
import 'setimmediate';
|
|
10
10
|
import { authToOwner } from '@atlaskit/media-core';
|
|
11
11
|
import { downloadUrl } from '@atlaskit/media-common/downloadUrl';
|
|
@@ -28,44 +28,40 @@ import { isMimeTypeSupportedByBrowser, getMediaTypeFromMimeType } from '@atlaski
|
|
|
28
28
|
import { shouldFetchRemoteFileStates, shouldFetchRemoteFileStatesObservable } from '../../utils/shouldFetchRemoteFileStates';
|
|
29
29
|
import { PollingFunction } from '../../utils/polling';
|
|
30
30
|
import { isEmptyFile } from '../../utils/detectEmptyFile';
|
|
31
|
+
import { getMediaFeatureFlag } from '@atlaskit/media-common';
|
|
31
32
|
export { isFileFetcherError, FileFetcherError } from './error';
|
|
32
33
|
export class FileFetcherImpl {
|
|
33
|
-
constructor(mediaStore) {
|
|
34
|
+
constructor(mediaStore, featureFlags) {
|
|
34
35
|
_defineProperty(this, "createDownloadFileStream", (id, collectionName, occurrenceKey) => {
|
|
35
36
|
const subject = createMediaSubject();
|
|
36
|
-
const poll = new PollingFunction();
|
|
37
|
+
const poll = new PollingFunction();
|
|
37
38
|
|
|
39
|
+
// ensure subject errors if polling exceeds max iterations or uncaught exception in executor
|
|
38
40
|
poll.onError = error => subject.error(error);
|
|
39
|
-
|
|
40
41
|
poll.execute(async () => {
|
|
41
42
|
const response = await this.dataloader.load({
|
|
42
43
|
id,
|
|
43
44
|
collectionName
|
|
44
45
|
});
|
|
45
|
-
|
|
46
46
|
if (!response) {
|
|
47
47
|
throw new FileFetcherError('emptyItems', id, {
|
|
48
48
|
collectionName,
|
|
49
49
|
occurrenceKey
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
|
-
|
|
53
52
|
if (isEmptyFile(response)) {
|
|
54
53
|
throw new FileFetcherError('zeroVersionFile', id, {
|
|
55
54
|
collectionName,
|
|
56
55
|
occurrenceKey
|
|
57
56
|
});
|
|
58
57
|
}
|
|
59
|
-
|
|
60
58
|
const fileState = mapMediaItemToFileState(id, response);
|
|
61
59
|
subject.next(fileState);
|
|
62
|
-
|
|
63
60
|
switch (fileState.status) {
|
|
64
61
|
case 'processing':
|
|
65
62
|
// the only case for continuing polling, otherwise this function is run once only
|
|
66
63
|
poll.next();
|
|
67
64
|
break;
|
|
68
|
-
|
|
69
65
|
case 'processed':
|
|
70
66
|
subject.complete();
|
|
71
67
|
break;
|
|
@@ -73,17 +69,53 @@ export class FileFetcherImpl {
|
|
|
73
69
|
});
|
|
74
70
|
return subject;
|
|
75
71
|
});
|
|
76
|
-
|
|
72
|
+
_defineProperty(this, "getUploadingFileStateBase", (file, upfrontId) => {
|
|
73
|
+
// TODO: DO not modify the input parameter 'content' attribute
|
|
74
|
+
if (typeof file.content === 'string') {
|
|
75
|
+
file.content = convertBase64ToBlob(file.content);
|
|
76
|
+
}
|
|
77
|
+
const {
|
|
78
|
+
content,
|
|
79
|
+
name = '' // name property is not available in base64 image
|
|
80
|
+
} = file;
|
|
81
|
+
const {
|
|
82
|
+
id,
|
|
83
|
+
occurrenceKey
|
|
84
|
+
} = upfrontId;
|
|
85
|
+
let preview;
|
|
86
|
+
// TODO [MSW-796]: get file size for base64
|
|
87
|
+
let size = 0;
|
|
88
|
+
let mimeType = '';
|
|
89
|
+
if (content instanceof Blob) {
|
|
90
|
+
size = content.size;
|
|
91
|
+
mimeType = content.type;
|
|
92
|
+
if (isMimeTypeSupportedByBrowser(content.type)) {
|
|
93
|
+
preview = {
|
|
94
|
+
value: content,
|
|
95
|
+
origin: 'local'
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const mediaType = getMediaTypeFromUploadableFile(file);
|
|
100
|
+
return {
|
|
101
|
+
id,
|
|
102
|
+
occurrenceKey,
|
|
103
|
+
name,
|
|
104
|
+
size,
|
|
105
|
+
mediaType,
|
|
106
|
+
mimeType,
|
|
107
|
+
preview
|
|
108
|
+
};
|
|
109
|
+
});
|
|
77
110
|
this.mediaStore = mediaStore;
|
|
111
|
+
this.featureFlags = featureFlags;
|
|
78
112
|
this.dataloader = createFileDataloader(mediaStore);
|
|
79
113
|
}
|
|
80
|
-
|
|
81
114
|
getFileState(id, options = {}) {
|
|
82
115
|
const {
|
|
83
116
|
collectionName,
|
|
84
117
|
occurrenceKey
|
|
85
118
|
} = options;
|
|
86
|
-
|
|
87
119
|
if (!isValidId(id)) {
|
|
88
120
|
const subject = createMediaSubject();
|
|
89
121
|
subject.error(new FileFetcherError('invalidFileId', id, {
|
|
@@ -92,22 +124,19 @@ export class FileFetcherImpl {
|
|
|
92
124
|
}));
|
|
93
125
|
return fromObservable(subject);
|
|
94
126
|
}
|
|
95
|
-
|
|
96
127
|
return fromObservable(getFileStreamsCache().getOrInsert(id, () => this.createDownloadFileStream(id, collectionName)));
|
|
97
128
|
}
|
|
98
|
-
|
|
99
129
|
getCurrentState(id, options) {
|
|
100
130
|
return toPromise(this.getFileState(id, options));
|
|
101
131
|
}
|
|
102
|
-
|
|
103
132
|
getArtifactURL(artifacts, artifactName, collectionName) {
|
|
104
133
|
return this.mediaStore.getArtifactURL(artifacts, artifactName, collectionName);
|
|
105
134
|
}
|
|
106
|
-
|
|
107
135
|
getFileBinaryURL(id, collectionName) {
|
|
108
136
|
return this.mediaStore.getFileBinaryURL(id, collectionName);
|
|
109
|
-
}
|
|
137
|
+
}
|
|
110
138
|
|
|
139
|
+
// TODO: ----- ADD TICKET TO PASS TRACE ID to this.dataloader.load
|
|
111
140
|
|
|
112
141
|
touchFiles(descriptors, collection, traceContext) {
|
|
113
142
|
return this.mediaStore.touchFiles({
|
|
@@ -118,7 +147,6 @@ export class FileFetcherImpl {
|
|
|
118
147
|
data
|
|
119
148
|
}) => data);
|
|
120
149
|
}
|
|
121
|
-
|
|
122
150
|
generateUploadableFileUpfrontIds(collection, traceContext) {
|
|
123
151
|
const id = uuid();
|
|
124
152
|
const occurrenceKey = uuid();
|
|
@@ -134,7 +162,6 @@ export class FileFetcherImpl {
|
|
|
134
162
|
deferredUploadId
|
|
135
163
|
};
|
|
136
164
|
}
|
|
137
|
-
|
|
138
165
|
async uploadExternal(url, collection, traceContext) {
|
|
139
166
|
const uploadableFileUpfrontIds = this.generateUploadableFileUpfrontIds(collection, traceContext);
|
|
140
167
|
const {
|
|
@@ -145,18 +172,16 @@ export class FileFetcherImpl {
|
|
|
145
172
|
const deferredBlob = fetch(url).then(response => response.blob()).catch(() => undefined);
|
|
146
173
|
const preview = new Promise(async (resolve, reject) => {
|
|
147
174
|
const blob = await deferredBlob;
|
|
148
|
-
|
|
149
175
|
if (!blob) {
|
|
150
176
|
reject('Could not fetch the blob');
|
|
151
177
|
}
|
|
152
|
-
|
|
153
178
|
resolve({
|
|
154
179
|
value: blob,
|
|
155
180
|
origin: 'remote'
|
|
156
181
|
});
|
|
157
182
|
});
|
|
158
|
-
const name = url.split('/').pop() || '';
|
|
159
|
-
|
|
183
|
+
const name = url.split('/').pop() || '';
|
|
184
|
+
// we create a initial fileState with the minimum info that we have at this point
|
|
160
185
|
const fileState = {
|
|
161
186
|
status: 'processing',
|
|
162
187
|
name,
|
|
@@ -167,16 +192,14 @@ export class FileFetcherImpl {
|
|
|
167
192
|
occurrenceKey,
|
|
168
193
|
preview
|
|
169
194
|
};
|
|
170
|
-
subject.next(fileState);
|
|
171
|
-
|
|
195
|
+
subject.next(fileState);
|
|
196
|
+
// we save it into the cache as soon as possible, in case someone subscribes
|
|
172
197
|
getFileStreamsCache().set(id, subject);
|
|
173
198
|
return new Promise(async (resolve, reject) => {
|
|
174
199
|
const blob = await deferredBlob;
|
|
175
|
-
|
|
176
200
|
if (!blob) {
|
|
177
201
|
return reject('Could not download remote file');
|
|
178
202
|
}
|
|
179
|
-
|
|
180
203
|
const {
|
|
181
204
|
type,
|
|
182
205
|
size
|
|
@@ -187,8 +210,9 @@ export class FileFetcherImpl {
|
|
|
187
210
|
collection,
|
|
188
211
|
name
|
|
189
212
|
};
|
|
190
|
-
const mediaType = getMediaTypeFromMimeType(type);
|
|
213
|
+
const mediaType = getMediaTypeFromMimeType(type);
|
|
191
214
|
|
|
215
|
+
// we emit a richer state after the blob is fetched
|
|
192
216
|
subject.next({
|
|
193
217
|
status: 'processing',
|
|
194
218
|
name,
|
|
@@ -198,8 +222,8 @@ export class FileFetcherImpl {
|
|
|
198
222
|
id,
|
|
199
223
|
occurrenceKey,
|
|
200
224
|
preview
|
|
201
|
-
});
|
|
202
|
-
|
|
225
|
+
});
|
|
226
|
+
// we don't want to wait for the file to be upload
|
|
203
227
|
this.upload(file, undefined, uploadableFileUpfrontIds, traceContext);
|
|
204
228
|
const dimensions = await getDimensionsFromBlob(mediaType, blob);
|
|
205
229
|
resolve({
|
|
@@ -208,37 +232,81 @@ export class FileFetcherImpl {
|
|
|
208
232
|
});
|
|
209
233
|
});
|
|
210
234
|
}
|
|
235
|
+
// TODO: make this the public upload method when the FF is removed
|
|
236
|
+
uploadAwlaysPullFileStates(file, controller, uploadableFileUpfrontIds, traceContext) {
|
|
237
|
+
const {
|
|
238
|
+
collection
|
|
239
|
+
} = file;
|
|
240
|
+
const upfrontId = uploadableFileUpfrontIds || this.generateUploadableFileUpfrontIds(collection, traceContext);
|
|
241
|
+
const {
|
|
242
|
+
id,
|
|
243
|
+
occurrenceKey
|
|
244
|
+
} = upfrontId;
|
|
245
|
+
const stateBase = this.getUploadingFileStateBase(file, upfrontId);
|
|
246
|
+
const subject = createMediaSubject();
|
|
247
|
+
getFileStreamsCache().set(id, subject);
|
|
248
|
+
const onProgress = progress => {
|
|
249
|
+
subject.next({
|
|
250
|
+
status: 'uploading',
|
|
251
|
+
...stateBase,
|
|
252
|
+
progress
|
|
253
|
+
});
|
|
254
|
+
};
|
|
255
|
+
let processingSubscription = new Subscription();
|
|
256
|
+
const onUploadFinish = error => {
|
|
257
|
+
if (error) {
|
|
258
|
+
return subject.error(error);
|
|
259
|
+
}
|
|
260
|
+
processingSubscription = this.createDownloadFileStream(id, collection, occurrenceKey).pipe(map(remoteFileState => ({
|
|
261
|
+
// merges base state with remote state
|
|
262
|
+
...stateBase,
|
|
263
|
+
...remoteFileState,
|
|
264
|
+
...overrideMediaTypeIfUnknown(remoteFileState, stateBase.mediaType)
|
|
265
|
+
}))).subscribe(subject);
|
|
266
|
+
};
|
|
267
|
+
const {
|
|
268
|
+
cancel
|
|
269
|
+
} = uploadFile(file, this.mediaStore, upfrontId, {
|
|
270
|
+
onUploadFinish,
|
|
271
|
+
onProgress
|
|
272
|
+
}, traceContext);
|
|
273
|
+
controller === null || controller === void 0 ? void 0 : controller.setAbort(() => {
|
|
274
|
+
cancel();
|
|
275
|
+
// TODO: filestate should turn to "Aborted" or something.
|
|
276
|
+
// Consider canceling an upload that is already finished
|
|
277
|
+
processingSubscription.unsubscribe();
|
|
278
|
+
});
|
|
211
279
|
|
|
212
|
-
|
|
280
|
+
// We should report progress asynchronously, since this is what consumer expects
|
|
281
|
+
// (otherwise in newUploadService file-converting event will be emitted before files-added)
|
|
282
|
+
setTimeout(onProgress, 0, 0);
|
|
283
|
+
return fromObservable(subject);
|
|
284
|
+
}
|
|
285
|
+
uploadConditionallyPullFileStates(file, controller, uploadableFileUpfrontIds, traceContext) {
|
|
213
286
|
if (typeof file.content === 'string') {
|
|
214
287
|
file.content = convertBase64ToBlob(file.content);
|
|
215
288
|
}
|
|
216
|
-
|
|
217
289
|
const {
|
|
218
290
|
content,
|
|
219
291
|
name = '',
|
|
220
292
|
// name property is not available in base64 image
|
|
221
293
|
collection
|
|
222
294
|
} = file;
|
|
223
|
-
|
|
224
295
|
if (!uploadableFileUpfrontIds) {
|
|
225
296
|
uploadableFileUpfrontIds = this.generateUploadableFileUpfrontIds(collection, traceContext);
|
|
226
297
|
}
|
|
227
|
-
|
|
228
298
|
const id = uploadableFileUpfrontIds.id;
|
|
229
299
|
const occurrenceKey = uploadableFileUpfrontIds.occurrenceKey;
|
|
230
300
|
let mimeType = '';
|
|
231
301
|
let size = 0;
|
|
232
|
-
let preview;
|
|
233
|
-
|
|
302
|
+
let preview;
|
|
303
|
+
// TODO [MSW-796]: get file size for base64
|
|
234
304
|
const mediaType = getMediaTypeFromUploadableFile(file);
|
|
235
305
|
const subject = createMediaSubject();
|
|
236
306
|
const processingSubscription = new Subscription();
|
|
237
|
-
|
|
238
307
|
if (content instanceof Blob) {
|
|
239
308
|
size = content.size;
|
|
240
309
|
mimeType = content.type;
|
|
241
|
-
|
|
242
310
|
if (isMimeTypeSupportedByBrowser(content.type)) {
|
|
243
311
|
preview = {
|
|
244
312
|
value: content,
|
|
@@ -246,7 +314,6 @@ export class FileFetcherImpl {
|
|
|
246
314
|
};
|
|
247
315
|
}
|
|
248
316
|
}
|
|
249
|
-
|
|
250
317
|
const stateBase = {
|
|
251
318
|
id,
|
|
252
319
|
occurrenceKey,
|
|
@@ -256,7 +323,6 @@ export class FileFetcherImpl {
|
|
|
256
323
|
mimeType,
|
|
257
324
|
preview
|
|
258
325
|
};
|
|
259
|
-
|
|
260
326
|
const onProgress = progress => {
|
|
261
327
|
subject.next({
|
|
262
328
|
status: 'uploading',
|
|
@@ -264,21 +330,19 @@ export class FileFetcherImpl {
|
|
|
264
330
|
progress
|
|
265
331
|
});
|
|
266
332
|
};
|
|
267
|
-
|
|
268
333
|
const onUploadFinish = error => {
|
|
269
334
|
if (error) {
|
|
270
335
|
return subject.error(error);
|
|
271
336
|
}
|
|
272
|
-
|
|
273
337
|
processingSubscription.add(shouldFetchRemoteFileStatesObservable(mediaType, mimeType, preview).pipe(concatMap(shouldFetchRemoteFileStates => {
|
|
274
338
|
if (shouldFetchRemoteFileStates) {
|
|
275
|
-
return this.createDownloadFileStream(id, collection, occurrenceKey).pipe(map(remoteFileState => ({
|
|
339
|
+
return this.createDownloadFileStream(id, collection, occurrenceKey).pipe(map(remoteFileState => ({
|
|
340
|
+
// merges base state with remote state
|
|
276
341
|
...stateBase,
|
|
277
342
|
...remoteFileState,
|
|
278
343
|
...overrideMediaTypeIfUnknown(remoteFileState, mediaType)
|
|
279
344
|
})));
|
|
280
345
|
}
|
|
281
|
-
|
|
282
346
|
return of({
|
|
283
347
|
status: 'processing',
|
|
284
348
|
representations: {},
|
|
@@ -286,31 +350,36 @@ export class FileFetcherImpl {
|
|
|
286
350
|
});
|
|
287
351
|
})).subscribe(subject));
|
|
288
352
|
};
|
|
289
|
-
|
|
290
353
|
const {
|
|
291
354
|
cancel
|
|
292
355
|
} = uploadFile(file, this.mediaStore, uploadableFileUpfrontIds, {
|
|
293
356
|
onUploadFinish,
|
|
294
357
|
onProgress
|
|
295
358
|
}, traceContext);
|
|
296
|
-
getFileStreamsCache().set(id, subject);
|
|
297
|
-
// (otherwise in newUploadService file-converting event will be emitted before files-added)
|
|
359
|
+
getFileStreamsCache().set(id, subject);
|
|
298
360
|
|
|
361
|
+
// We should report progress asynchronously, since this is what consumer expects
|
|
362
|
+
// (otherwise in newUploadService file-converting event will be emitted before files-added)
|
|
299
363
|
setTimeout(() => {
|
|
300
364
|
onProgress(0);
|
|
301
365
|
}, 0);
|
|
302
|
-
|
|
303
366
|
if (controller) {
|
|
304
367
|
controller.setAbort(() => {
|
|
305
368
|
cancel();
|
|
306
369
|
processingSubscription.unsubscribe();
|
|
307
370
|
});
|
|
308
371
|
}
|
|
309
|
-
|
|
310
372
|
return fromObservable(subject);
|
|
311
|
-
}
|
|
312
|
-
|
|
373
|
+
}
|
|
374
|
+
upload(file, controller, uploadableFileUpfrontIds, traceContext) {
|
|
375
|
+
const shouldAlwaysFetchFileState = getMediaFeatureFlag('fetchFileStateAfterUpload', this.featureFlags);
|
|
376
|
+
if (shouldAlwaysFetchFileState) {
|
|
377
|
+
return this.uploadAwlaysPullFileStates(file, controller, uploadableFileUpfrontIds, traceContext);
|
|
378
|
+
}
|
|
379
|
+
return this.uploadConditionallyPullFileStates(file, controller, uploadableFileUpfrontIds, traceContext);
|
|
380
|
+
}
|
|
313
381
|
|
|
382
|
+
// TODO: ----- ADD TICKET
|
|
314
383
|
async downloadBinary(id, name = 'download', collectionName) {
|
|
315
384
|
const url = await this.mediaStore.getFileBinaryURL(id, collectionName);
|
|
316
385
|
downloadUrl(url, {
|
|
@@ -322,7 +391,6 @@ export class FileFetcherImpl {
|
|
|
322
391
|
viewingLevel: 'download'
|
|
323
392
|
});
|
|
324
393
|
}
|
|
325
|
-
|
|
326
394
|
async copyFile(source, destination, options = {}, traceContext) {
|
|
327
395
|
const {
|
|
328
396
|
authProvider,
|
|
@@ -359,13 +427,14 @@ export class FileFetcherImpl {
|
|
|
359
427
|
};
|
|
360
428
|
const cache = getFileStreamsCache();
|
|
361
429
|
let processingSubscription;
|
|
362
|
-
|
|
363
430
|
try {
|
|
364
431
|
const {
|
|
365
432
|
data: copiedFile
|
|
366
|
-
} = await mediaStore.copyFileWithToken(body, params, traceContext);
|
|
433
|
+
} = await mediaStore.copyFileWithToken(body, params, traceContext);
|
|
367
434
|
|
|
368
|
-
|
|
435
|
+
// if we were passed a "mimeType", we propagate it into copiedFileWithMimeType
|
|
436
|
+
const copiedFileWithMimeType = {
|
|
437
|
+
...copiedFile,
|
|
369
438
|
...(mimeType ? {
|
|
370
439
|
mimeType
|
|
371
440
|
} : undefined)
|
|
@@ -373,29 +442,33 @@ export class FileFetcherImpl {
|
|
|
373
442
|
const {
|
|
374
443
|
id: copiedId,
|
|
375
444
|
mimeType: copiedMimeType
|
|
376
|
-
} = copiedFileWithMimeType;
|
|
377
|
-
// it's better to deduce it from "copiedMimeType" using getMediaTypeFromMimeType()
|
|
445
|
+
} = copiedFileWithMimeType;
|
|
378
446
|
|
|
447
|
+
// backend may return an "unknown" mediaType just after the copy
|
|
448
|
+
// it's better to deduce it from "copiedMimeType" using getMediaTypeFromMimeType()
|
|
379
449
|
const mediaType = copiedMimeType ? getMediaTypeFromMimeType(copiedMimeType) : 'unknown';
|
|
380
450
|
const copiedFileState = mapMediaFileToFileState({
|
|
381
451
|
data: copiedFileWithMimeType
|
|
382
452
|
});
|
|
383
453
|
const fileCache = cache.get(copiedId);
|
|
384
|
-
const subject = fileCache || createMediaSubject();
|
|
454
|
+
const subject = fileCache || createMediaSubject();
|
|
385
455
|
|
|
456
|
+
// if we were passed a "preview", we propagate it into the copiedFileState
|
|
386
457
|
const previewOverride = !isErrorFileState(copiedFileState) && !!preview ? {
|
|
387
458
|
preview
|
|
388
459
|
} : {};
|
|
389
|
-
|
|
390
|
-
|
|
460
|
+
if (!isFinalFileState(copiedFileState) &&
|
|
461
|
+
// mimeType should always be returned by "copyFileWithToken"
|
|
391
462
|
// but in case it's not, we don't want to penalize "copyFile"
|
|
392
463
|
copiedMimeType && (await shouldFetchRemoteFileStates(mediaType, copiedMimeType, preview))) {
|
|
393
|
-
subject.next({
|
|
464
|
+
subject.next({
|
|
465
|
+
...copiedFileState,
|
|
394
466
|
...overrideMediaTypeIfUnknown(copiedFileState, mediaType),
|
|
395
467
|
...previewOverride
|
|
396
468
|
});
|
|
397
469
|
processingSubscription = this.createDownloadFileStream(copiedId, destinationCollectionName, occurrenceKey).subscribe({
|
|
398
|
-
next: remoteFileState => subject.next({
|
|
470
|
+
next: remoteFileState => subject.next({
|
|
471
|
+
...remoteFileState,
|
|
399
472
|
...overrideMediaTypeIfUnknown(remoteFileState, mediaType),
|
|
400
473
|
...(!isErrorFileState(remoteFileState) && previewOverride)
|
|
401
474
|
}),
|
|
@@ -403,24 +476,21 @@ export class FileFetcherImpl {
|
|
|
403
476
|
complete: () => subject.complete()
|
|
404
477
|
});
|
|
405
478
|
} else if (!isProcessingFileState(copiedFileState)) {
|
|
406
|
-
subject.next({
|
|
479
|
+
subject.next({
|
|
480
|
+
...copiedFileState,
|
|
407
481
|
...(!isErrorFileState(copiedFileState) && previewOverride)
|
|
408
482
|
});
|
|
409
483
|
}
|
|
410
|
-
|
|
411
484
|
if (!cache.has(copiedId)) {
|
|
412
485
|
getFileStreamsCache().set(copiedId, subject);
|
|
413
486
|
}
|
|
414
|
-
|
|
415
487
|
return copiedFile;
|
|
416
488
|
} catch (error) {
|
|
417
489
|
if (processingSubscription) {
|
|
418
490
|
processingSubscription.unsubscribe();
|
|
419
491
|
}
|
|
420
|
-
|
|
421
492
|
if (replaceFileId) {
|
|
422
493
|
const fileCache = cache.get(replaceFileId);
|
|
423
|
-
|
|
424
494
|
if (fileCache) {
|
|
425
495
|
fileCache.error(error);
|
|
426
496
|
} else {
|
|
@@ -428,9 +498,7 @@ export class FileFetcherImpl {
|
|
|
428
498
|
cache.set(id, createMediaSubject(error));
|
|
429
499
|
}
|
|
430
500
|
}
|
|
431
|
-
|
|
432
501
|
throw error;
|
|
433
502
|
}
|
|
434
503
|
}
|
|
435
|
-
|
|
436
504
|
}
|
|
@@ -5,7 +5,9 @@ import { FileFetcherImpl } from './file-fetcher';
|
|
|
5
5
|
import { StargateClient } from './stargate-client';
|
|
6
6
|
export class MediaClient {
|
|
7
7
|
// mobile upload is lazily loaded
|
|
8
|
+
|
|
8
9
|
// Deprecated value introduced for backward compatibility with Context
|
|
10
|
+
|
|
9
11
|
constructor(mediaClientConfig, featureFlags) {
|
|
10
12
|
this.mediaClientConfig = mediaClientConfig;
|
|
11
13
|
this.featureFlags = featureFlags;
|
|
@@ -15,49 +17,37 @@ export class MediaClient {
|
|
|
15
17
|
}, featureFlags);
|
|
16
18
|
this.config = mediaClientConfig;
|
|
17
19
|
this.collection = new CollectionFetcher(this.mediaStore);
|
|
18
|
-
this.file = new FileFetcherImpl(this.mediaStore);
|
|
20
|
+
this.file = new FileFetcherImpl(this.mediaStore, featureFlags);
|
|
19
21
|
this.eventEmitter = new EventEmitter2();
|
|
20
22
|
this.stargate = new StargateClient(mediaClientConfig.stargateBaseUrl);
|
|
21
23
|
}
|
|
22
|
-
|
|
23
24
|
getImage(id, params, controller, fetchMaxRes, traceContext) {
|
|
24
25
|
return this.mediaStore.getImage(id, params, controller, fetchMaxRes, traceContext);
|
|
25
26
|
}
|
|
26
|
-
|
|
27
27
|
getImageUrl(id, params) {
|
|
28
28
|
return this.mediaStore.getFileImageURL(id, params);
|
|
29
29
|
}
|
|
30
|
-
|
|
31
30
|
getImageUrlSync(id, params) {
|
|
32
31
|
return this.mediaStore.getFileImageURLSync(id, params);
|
|
33
32
|
}
|
|
34
|
-
|
|
35
33
|
async getImageMetadata(id, params) {
|
|
36
34
|
return (await this.mediaStore.getImageMetadata(id, params)).metadata;
|
|
37
35
|
}
|
|
38
|
-
|
|
39
36
|
async mobileUploadPromise() {
|
|
40
37
|
if (this.mobileUpload) {
|
|
41
38
|
return this.mobileUpload;
|
|
42
39
|
}
|
|
43
|
-
|
|
44
|
-
const module = await import(
|
|
45
|
-
/* webpackChunkName: "@atlaskit-internal_media-client-mobile-upload" */
|
|
46
|
-
'./mobile-upload');
|
|
40
|
+
const module = await import( /* webpackChunkName: "@atlaskit-internal_media-client-mobile-upload" */'./mobile-upload');
|
|
47
41
|
this.mobileUpload = new module.MobileUploadImpl(this.mediaStore);
|
|
48
42
|
return this.mobileUpload;
|
|
49
43
|
}
|
|
50
|
-
|
|
51
44
|
on(event, listener) {
|
|
52
45
|
this.eventEmitter.on(event, listener);
|
|
53
46
|
}
|
|
54
|
-
|
|
55
47
|
off(event, listener) {
|
|
56
48
|
this.eventEmitter.off(event, listener);
|
|
57
49
|
}
|
|
58
|
-
|
|
59
50
|
emit(event, payload) {
|
|
60
51
|
return this.eventEmitter.emit(event, payload);
|
|
61
52
|
}
|
|
62
|
-
|
|
63
53
|
}
|
|
@@ -5,7 +5,6 @@ export class MediaStoreError extends BaseMediaClientError {
|
|
|
5
5
|
this.reason = reason;
|
|
6
6
|
this.innerError = innerError;
|
|
7
7
|
}
|
|
8
|
-
|
|
9
8
|
get attributes() {
|
|
10
9
|
const {
|
|
11
10
|
reason,
|
|
@@ -16,7 +15,6 @@ export class MediaStoreError extends BaseMediaClientError {
|
|
|
16
15
|
innerError
|
|
17
16
|
};
|
|
18
17
|
}
|
|
19
|
-
|
|
20
18
|
}
|
|
21
19
|
export function isMediaStoreError(err) {
|
|
22
20
|
return err instanceof MediaStoreError;
|