Upload: fix redux key clash
## Issue `params` is the "final" value that will be passed to the SDK and `channel` is not a valid argument (it should be `channel_name`). Also, it seems like we only pass the channel ID now and skip the channel name entirely. For the anonymous case, a clash will still happen when since the channel part is hardcoded to `anonymous`. ## Approach Generate a guid in `params` and use that as the key to handle all the cases above. We couldn't use the `uploadUrl` because v1 doesn't have it. The old formula is retained to allow users to retry or cancel their existing uploads one last time (otherwise it will persist forever). The next upload will be using the new key.
This commit is contained in:
parent
994d9c6027
commit
ded021cc76
6 changed files with 24 additions and 12 deletions
3
flow-typed/publish.js
vendored
3
flow-typed/publish.js
vendored
|
@ -62,7 +62,8 @@ declare type FileUploadSdkParams = {
|
||||||
remote_url?: string,
|
remote_url?: string,
|
||||||
thumbnail_url?: string,
|
thumbnail_url?: string,
|
||||||
title?: string,
|
title?: string,
|
||||||
// Temporary values
|
// Temporary values; remove when passing to SDK
|
||||||
|
guid: string,
|
||||||
uploadUrl?: string,
|
uploadUrl?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,10 @@ export default function WebUploadItem(props: Props) {
|
||||||
if (serializeFileObj(newFile) === fileFingerprint) {
|
if (serializeFileObj(newFile) === fileFingerprint) {
|
||||||
setShowFileSelector(false);
|
setShowFileSelector(false);
|
||||||
doPublishResume({ ...params, file_path: newFile });
|
doPublishResume({ ...params, file_path: newFile });
|
||||||
|
if (!params.guid) {
|
||||||
|
// Can remove this if-block after January 2022.
|
||||||
|
doUpdateUploadRemove(params);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
doOpenModal(MODALS.CONFIRM, {
|
doOpenModal(MODALS.CONFIRM, {
|
||||||
title: __('Invalid file'),
|
title: __('Invalid file'),
|
||||||
|
|
|
@ -6,7 +6,9 @@ import * as ACTIONS from 'constants/action_types';
|
||||||
import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses';
|
import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses';
|
||||||
import { CHANNEL_ANONYMOUS } from 'constants/claim';
|
import { CHANNEL_ANONYMOUS } from 'constants/claim';
|
||||||
|
|
||||||
const getKeyFromParam = (params) => `${params.name}#${params.channel || 'anonymous'}`;
|
// This is the old key formula. Retain it for now to allow users to delete
|
||||||
|
// any pending uploads. Can be removed from January 2022 onwards.
|
||||||
|
const getOldKeyFromParam = (params) => `${params.name}#${params.channel || 'anonymous'}`;
|
||||||
|
|
||||||
type PublishState = {
|
type PublishState = {
|
||||||
editingURI: ?string,
|
editingURI: ?string,
|
||||||
|
@ -138,10 +140,9 @@ export const publishReducer = handleActions(
|
||||||
},
|
},
|
||||||
[ACTIONS.UPDATE_UPLOAD_ADD]: (state: PublishState, action) => {
|
[ACTIONS.UPDATE_UPLOAD_ADD]: (state: PublishState, action) => {
|
||||||
const { file, params, uploader } = action.data;
|
const { file, params, uploader } = action.data;
|
||||||
const key = getKeyFromParam(params);
|
|
||||||
const currentUploads = Object.assign({}, state.currentUploads);
|
const currentUploads = Object.assign({}, state.currentUploads);
|
||||||
|
|
||||||
currentUploads[key] = {
|
currentUploads[params.guid] = {
|
||||||
file,
|
file,
|
||||||
fileFingerprint: file ? serializeFileObj(file) : undefined, // TODO: get hash instead?
|
fileFingerprint: file ? serializeFileObj(file) : undefined, // TODO: get hash instead?
|
||||||
progress: '0',
|
progress: '0',
|
||||||
|
@ -154,7 +155,7 @@ export const publishReducer = handleActions(
|
||||||
},
|
},
|
||||||
[ACTIONS.UPDATE_UPLOAD_PROGRESS]: (state: PublishState, action) => {
|
[ACTIONS.UPDATE_UPLOAD_PROGRESS]: (state: PublishState, action) => {
|
||||||
const { params, progress, status } = action.data;
|
const { params, progress, status } = action.data;
|
||||||
const key = getKeyFromParam(params);
|
const key = params.guid || getOldKeyFromParam(params);
|
||||||
const currentUploads = Object.assign({}, state.currentUploads);
|
const currentUploads = Object.assign({}, state.currentUploads);
|
||||||
|
|
||||||
if (!currentUploads[key]) {
|
if (!currentUploads[key]) {
|
||||||
|
@ -181,11 +182,9 @@ export const publishReducer = handleActions(
|
||||||
},
|
},
|
||||||
[ACTIONS.UPDATE_UPLOAD_REMOVE]: (state: PublishState, action) => {
|
[ACTIONS.UPDATE_UPLOAD_REMOVE]: (state: PublishState, action) => {
|
||||||
const { params } = action.data;
|
const { params } = action.data;
|
||||||
const key = getKeyFromParam(params);
|
const key = params.guid || getOldKeyFromParam(params);
|
||||||
const currentUploads = Object.assign({}, state.currentUploads);
|
const currentUploads = Object.assign({}, state.currentUploads);
|
||||||
|
|
||||||
delete currentUploads[key];
|
delete currentUploads[key];
|
||||||
|
|
||||||
return { ...state, currentUploads };
|
return { ...state, currentUploads };
|
||||||
},
|
},
|
||||||
[ACTIONS.REHYDRATE]: (state: PublishState, action) => {
|
[ACTIONS.REHYDRATE]: (state: PublishState, action) => {
|
||||||
|
|
|
@ -30,10 +30,12 @@ export function makeUploadRequest(
|
||||||
delete params['remote_url'];
|
delete params['remote_url'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { uploadUrl, guid, ...sdkParams } = params;
|
||||||
|
|
||||||
const jsonPayload = JSON.stringify({
|
const jsonPayload = JSON.stringify({
|
||||||
jsonrpc: '2.0',
|
jsonrpc: '2.0',
|
||||||
method: ENDPOINT_METHOD,
|
method: ENDPOINT_METHOD,
|
||||||
params,
|
params: sdkParams,
|
||||||
id: new Date().getTime(),
|
id: new Date().getTime(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -38,13 +38,12 @@ export function makeResumableUploadRequest(
|
||||||
reject(new Error('Publish: v2 does not support remote_url'));
|
reject(new Error('Publish: v2 does not support remote_url'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const payloadParams = Object.assign({}, params);
|
const { uploadUrl, guid, ...sdkParams } = params;
|
||||||
delete payloadParams.uploadUrl; // cleanup
|
|
||||||
|
|
||||||
const jsonPayload = JSON.stringify({
|
const jsonPayload = JSON.stringify({
|
||||||
jsonrpc: '2.0',
|
jsonrpc: '2.0',
|
||||||
method: RESUMABLE_ENDPOINT_METHOD,
|
method: RESUMABLE_ENDPOINT_METHOD,
|
||||||
params: payloadParams,
|
params: sdkParams,
|
||||||
id: new Date().getTime(),
|
id: new Date().getTime(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as tus from 'tus-js-client';
|
import * as tus from 'tus-js-client';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
import { makeUploadRequest } from './publish-v1';
|
import { makeUploadRequest } from './publish-v1';
|
||||||
import { makeResumableUploadRequest } from './publish-v2';
|
import { makeResumableUploadRequest } from './publish-v2';
|
||||||
|
|
||||||
|
@ -34,6 +35,12 @@ export default function apiPublishCallViaWeb(
|
||||||
params.file_path = '__POST_FILE__';
|
params.file_path = '__POST_FILE__';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a random ID to serve as the redux key.
|
||||||
|
// If it already exists, then it is a resumed session.
|
||||||
|
if (!params.guid) {
|
||||||
|
params.guid = uuid();
|
||||||
|
}
|
||||||
|
|
||||||
const useV1 = remoteUrl || preview || !tus.isSupported;
|
const useV1 = remoteUrl || preview || !tus.isSupported;
|
||||||
|
|
||||||
// Note: both function signature (params) should match.
|
// Note: both function signature (params) should match.
|
||||||
|
|
Loading…
Reference in a new issue