From 9d71be9b1b21b1bd6e23ea092cd5cdef3796e83d Mon Sep 17 00:00:00 2001 From: Thomas Zarebczan Date: Tue, 23 Jul 2019 12:22:26 -0400 Subject: [PATCH 1/6] [wip] range requests --- src/redux/actions/file.js | 2 +- src/redux/reducers/file_info.js | 4 +++- src/redux/selectors/file_info.js | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/redux/actions/file.js b/src/redux/actions/file.js index 337f85f..0afe464 100644 --- a/src/redux/actions/file.js +++ b/src/redux/actions/file.js @@ -55,7 +55,7 @@ export function doFileGet(uri: string, saveFile: boolean = true) { dispatch( doToast({ - message: `Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`, + message: `Failed to view ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`, isError: true, }) ); diff --git a/src/redux/reducers/file_info.js b/src/redux/reducers/file_info.js index dbc5e86..5f20148 100644 --- a/src/redux/reducers/file_info.js +++ b/src/redux/reducers/file_info.js @@ -91,13 +91,15 @@ reducers[ACTIONS.DOWNLOADING_PROGRESSED] = (state, action) => { }; reducers[ACTIONS.DOWNLOADING_CANCELED] = (state, action) => { - const { outpoint } = action.data; + const { uri, outpoint } = action.data; const newDownloading = Object.assign({}, state.downloadingByOutpoint); delete newDownloading[outpoint]; + delete newLoading[uri]; return Object.assign({}, state, { downloadingByOutpoint: newDownloading, + urisLoading: newLoading, }); }; diff --git a/src/redux/selectors/file_info.js b/src/redux/selectors/file_info.js index f323734..7c045fe 100644 --- a/src/redux/selectors/file_info.js +++ b/src/redux/selectors/file_info.js @@ -72,7 +72,7 @@ export const selectFileInfosDownloaded = createSelector( return ( fileInfo && myClaimIds.indexOf(fileInfo.claim_id) === -1 && - (fileInfo.completed || fileInfo.written_bytes) + (fileInfo.completed || fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0 ) ); }) ); -- 2.45.3 From faf44023091c7a4d38c03076360ed348ea5b3522 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Fri, 2 Aug 2019 02:21:28 -0400 Subject: [PATCH 2/6] working? --- dist/bundle.es.js | 94 ++++++++++++++++++++++++-------- dist/flow-typed/Lbry.js | 2 +- flow-typed/Lbry.js | 2 +- package.json | 1 + src/index.js | 4 ++ src/lbry.js | 47 ++++++++++------ src/redux/actions/file.js | 27 +++++++-- src/redux/selectors/file.js | 9 ++- src/redux/selectors/file_info.js | 42 +++++++++++++- yarn.lock | 5 ++ 10 files changed, 181 insertions(+), 52 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index c138c15..2177543 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } require('proxy-polyfill'); +var mime = _interopDefault(require('mime')); var reselect = require('reselect'); var uuid = _interopDefault(require('uuid/v4')); var fs = _interopDefault(require('fs')); @@ -696,23 +697,30 @@ const Lbry = { }, // Returns a human readable media type based on the content type or extension of a file that is returned by the sdk - getMediaType: (contentType, extname) => { - if (extname) { - const formats = [[/^(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'], [/^(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'], [/^(html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org)$/i, 'document'], [/^(stl|obj|fbx|gcode)$/i, '3D-file']]; + getMediaType: (contentType, fileName) => { + const formats = [[/\.(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'], [/\.(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'], [/\.(h|go|ja|java|js|jsx|c|cpp|cs|css|rb|scss|sh|php|py)$/i, 'script'], [/\.(json|csv|txt|log|md|markdown|docx|pdf|xml|yml|yaml)$/i, 'document'], [/\.(pdf|odf|doc|docx|epub|org|rtf)$/i, 'e-book'], [/\.(stl|obj|fbx|gcode)$/i, '3D-file'], [/\.(cbr|cbt|cbz)$/i, 'comic-book']]; + + const extName = mime.getExtension(contentType); + const fileExt = extName ? `.${extName}` : null; + const testString = fileName || fileExt; + + // Get mediaType from file extension + if (testString) { const res = formats.reduce((ret, testpair) => { - switch (testpair[0].test(ret)) { - case true: - return testpair[1]; - default: - return ret; - } - }, extname); - return res === extname ? 'unknown' : res; - } else if (contentType) { - // $FlowFixMe + const [regex, mediaType] = testpair; + + return regex.test(ret) ? mediaType : ret; + }, testString); + + if (res !== testString) return res; + } + + // Get mediaType from contentType + if (contentType) { return (/^[^/]+/.exec(contentType)[0] ); } + return 'unknown'; }, @@ -2447,7 +2455,7 @@ const makeSelectLoadingForUri = uri => reselect.createSelector(selectUrisLoading const selectFileInfosDownloaded = reselect.createSelector(selectFileInfosByOutpoint, selectMyClaims, (byOutpoint, myClaims) => Object.values(byOutpoint).filter(fileInfo => { const myClaimIds = myClaims.map(claim => claim.claim_id); - return fileInfo && myClaimIds.indexOf(fileInfo.claim_id) === -1 && (fileInfo.completed || fileInfo.written_bytes); + return fileInfo && myClaimIds.indexOf(fileInfo.claim_id) === -1 && (fileInfo.completed || fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0); })); // export const selectFileInfoForUri = (state, props) => { @@ -2586,6 +2594,27 @@ const selectDownloadedUris = reselect.createSelector(selectFileInfosDownloaded, // We should use permament_url but it doesn't exist in file_list info => info.slice().reverse().map(claim => `lbry://${claim.claim_name}#${claim.claim_id}`)); +const makeSelectMediaTypeForUri = uri => reselect.createSelector(makeSelectFileInfoForUri(uri), makeSelectContentTypeForUri(uri), (fileInfo, contentType) => { + if (!fileInfo && !contentType) { + return undefined; + } + + const fileName = fileInfo && fileInfo.file_name; + return lbryProxy.getMediaType(contentType, fileName); +}); + +const makeSelectUriIsStreamable = uri => reselect.createSelector(makeSelectMediaTypeForUri(uri), mediaType => { + const isStreamable = ['audio', 'video', 'image'].indexOf(mediaType) !== -1; + return isStreamable; +}); + +const makeSelectDownloadPathForUri = uri => reselect.createSelector(makeSelectFileInfoForUri(uri), fileInfo => { + return fileInfo && fileInfo.download_path; +}); +const makeSelectFileNameForUri = uri => reselect.createSelector(makeSelectFileInfoForUri(uri), fileInfo => { + return fileInfo && fileInfo.file_name; +}); + // const selectState$4 = state => state.file || {}; @@ -2600,11 +2629,13 @@ const selectPurchasedStreamingUrls = reselect.createSelector(selectState$4, stat const selectLastPurchasedUri = reselect.createSelector(selectState$4, state => state.purchasedUris.length > 0 ? state.purchasedUris[state.purchasedUris.length - 1] : null); -const makeSelectStreamingUrlForUri = uri => reselect.createSelector(selectPurchasedStreamingUrls, streamingUrls => streamingUrls && streamingUrls[uri]); +const makeSelectStreamingUrlForUri = uri => reselect.createSelector(makeSelectFileInfoForUri(uri), fileInfo => { + return fileInfo && fileInfo.streaming_url; +}); // -function doFileGet(uri, saveFile = true) { +function doFileGet(uri, saveFile = true, onSuccess) { return dispatch => { dispatch({ type: LOADING_FILE_STARTED, @@ -2615,7 +2646,7 @@ function doFileGet(uri, saveFile = true) { // set save_file argument to True to save the file (old behaviour) lbryProxy.get({ uri, save_file: saveFile }).then(streamInfo => { - const timeout = streamInfo === null || typeof streamInfo !== 'object'; + const timeout = streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout'; if (timeout) { dispatch({ @@ -2633,8 +2664,19 @@ function doFileGet(uri, saveFile = true) { const { streaming_url: streamingUrl } = streamInfo; dispatch({ type: PURCHASE_URI_COMPLETED, - data: { uri, streamingUrl: !saveFile && streamingUrl ? streamingUrl : null } + data: { uri, streamingUrl } }); + dispatch({ + type: FETCH_FILE_INFO_COMPLETED, + data: { + fileInfo: streamInfo, + outpoint: streamInfo.outpoint + } + }); + + if (onSuccess) { + onSuccess(streamInfo); + } } }).catch(() => { dispatch({ @@ -2647,14 +2689,14 @@ function doFileGet(uri, saveFile = true) { }); dispatch(doToast({ - message: `Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`, + message: `Failed to view ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`, isError: true })); }); }; } -function doPurchaseUri(uri, costInfo, saveFile = true) { +function doPurchaseUri(uri, costInfo, saveFile = true, onSuccess) { return (dispatch, getState) => { dispatch({ type: PURCHASE_URI_STARTED, @@ -2685,7 +2727,7 @@ function doPurchaseUri(uri, costInfo, saveFile = true) { return; } - dispatch(doFileGet(uri, saveFile)); + dispatch(doFileGet(uri, saveFile, onSuccess)); }; } @@ -3921,13 +3963,15 @@ reducers$2[DOWNLOADING_PROGRESSED] = (state, action) => { }; reducers$2[DOWNLOADING_CANCELED] = (state, action) => { - const { outpoint } = action.data; + const { uri, outpoint } = action.data; const newDownloading = Object.assign({}, state.downloadingByOutpoint); delete newDownloading[outpoint]; + delete newLoading[uri]; return Object.assign({}, state, { - downloadingByOutpoint: newDownloading + downloadingByOutpoint: newDownloading, + urisLoading: newLoading }); }; @@ -4842,12 +4886,15 @@ exports.makeSelectContentPositionForUri = makeSelectContentPositionForUri; exports.makeSelectContentTypeForUri = makeSelectContentTypeForUri; exports.makeSelectCoverForUri = makeSelectCoverForUri; exports.makeSelectDateForUri = makeSelectDateForUri; +exports.makeSelectDownloadPathForUri = makeSelectDownloadPathForUri; exports.makeSelectDownloadingForUri = makeSelectDownloadingForUri; exports.makeSelectFetchingChannelClaims = makeSelectFetchingChannelClaims; exports.makeSelectFileInfoForUri = makeSelectFileInfoForUri; +exports.makeSelectFileNameForUri = makeSelectFileNameForUri; exports.makeSelectFirstRecommendedFileForUri = makeSelectFirstRecommendedFileForUri; exports.makeSelectIsUriResolving = makeSelectIsUriResolving; exports.makeSelectLoadingForUri = makeSelectLoadingForUri; +exports.makeSelectMediaTypeForUri = makeSelectMediaTypeForUri; exports.makeSelectMetadataForUri = makeSelectMetadataForUri; exports.makeSelectMetadataItemForUri = makeSelectMetadataItemForUri; exports.makeSelectNsfwCountForChannel = makeSelectNsfwCountForChannel; @@ -4864,6 +4911,7 @@ exports.makeSelectThumbnailForUri = makeSelectThumbnailForUri; exports.makeSelectTitleForUri = makeSelectTitleForUri; exports.makeSelectTotalItemsForChannel = makeSelectTotalItemsForChannel; exports.makeSelectTotalPagesForChannel = makeSelectTotalPagesForChannel; +exports.makeSelectUriIsStreamable = makeSelectUriIsStreamable; exports.normalizeURI = normalizeURI; exports.notificationsReducer = notificationsReducer; exports.parseQueryParams = parseQueryParams; diff --git a/dist/flow-typed/Lbry.js b/dist/flow-typed/Lbry.js index 335eda1..a403ffb 100644 --- a/dist/flow-typed/Lbry.js +++ b/dist/flow-typed/Lbry.js @@ -68,7 +68,7 @@ declare type ResolveResponse = { [string]: Claim | { error?: {} }, }; -declare type GetResponse = FileListItem; +declare type GetResponse = FileListItem & { error?: string }; declare type GenericTxResponse = { height: number, diff --git a/flow-typed/Lbry.js b/flow-typed/Lbry.js index 335eda1..a403ffb 100644 --- a/flow-typed/Lbry.js +++ b/flow-typed/Lbry.js @@ -68,7 +68,7 @@ declare type ResolveResponse = { [string]: Claim | { error?: {} }, }; -declare type GetResponse = FileListItem; +declare type GetResponse = FileListItem & { error?: string }; declare type GenericTxResponse = { height: number, diff --git a/package.json b/package.json index 21b595f..8cba56d 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "format": "prettier 'src/**/*.{js,json}' --write" }, "dependencies": { + "mime": "^2.4.4", "proxy-polyfill": "0.1.6", "reselect": "^3.0.0", "uuid": "^3.3.2" diff --git a/src/index.js b/src/index.js index 2f93891..9a5574e 100644 --- a/src/index.js +++ b/src/index.js @@ -217,6 +217,10 @@ export { selectFileListDownloadedSort, selectFileListPublishedSort, selectDownloadedUris, + makeSelectMediaTypeForUri, + makeSelectUriIsStreamable, + makeSelectDownloadPathForUri, + makeSelectFileNameForUri, } from 'redux/selectors/file_info'; export { diff --git a/src/lbry.js b/src/lbry.js index 07fe1f0..5ceb6dd 100644 --- a/src/lbry.js +++ b/src/lbry.js @@ -1,5 +1,6 @@ // @flow import 'proxy-polyfill'; +import mime from 'mime'; const CHECK_DAEMON_STARTED_TRY_NUMBER = 200; // @@ -32,27 +33,37 @@ const Lbry: LbryTypes = { }, // Returns a human readable media type based on the content type or extension of a file that is returned by the sdk - getMediaType: (contentType: string, extname: ?string) => { - if (extname) { - const formats = [ - [/^(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'], - [/^(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'], - [/^(html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org)$/i, 'document'], - [/^(stl|obj|fbx|gcode)$/i, '3D-file'], - ]; + getMediaType: (contentType?: string, fileName: ?string) => { + const formats = [ + [/\.(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'], + [/\.(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'], + [/\.(h|go|ja|java|js|jsx|c|cpp|cs|css|rb|scss|sh|php|py)$/i, 'script'], + [/\.(json|csv|txt|log|md|markdown|docx|pdf|xml|yml|yaml)$/i, 'document'], + [/\.(pdf|odf|doc|docx|epub|org|rtf)$/i, 'e-book'], + [/\.(stl|obj|fbx|gcode)$/i, '3D-file'], + [/\.(cbr|cbt|cbz)$/i, 'comic-book'], + ]; + + const extName = mime.getExtension(contentType); + const fileExt = extName ? `.${extName}` : null; + const testString = fileName || fileExt; + + // Get mediaType from file extension + if (testString) { const res = formats.reduce((ret, testpair) => { - switch (testpair[0].test(ret)) { - case true: - return testpair[1]; - default: - return ret; - } - }, extname); - return res === extname ? 'unknown' : res; - } else if (contentType) { - // $FlowFixMe + const [regex, mediaType] = testpair; + + return regex.test(ret) ? mediaType : ret; + }, testString); + + if (res !== testString) return res; + } + + // Get mediaType from contentType + if (contentType) { return /^[^/]+/.exec(contentType)[0]; } + return 'unknown'; }, diff --git a/src/redux/actions/file.js b/src/redux/actions/file.js index 0afe464..305ff4f 100644 --- a/src/redux/actions/file.js +++ b/src/redux/actions/file.js @@ -9,7 +9,7 @@ import { makeSelectStreamingUrlForUri } from 'redux/selectors/file'; type Dispatch = (action: any) => any; type GetState = () => { file: FileState }; -export function doFileGet(uri: string, saveFile: boolean = true) { +export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: GetResponse => any) { return (dispatch: Dispatch) => { dispatch({ type: ACTIONS.LOADING_FILE_STARTED, @@ -21,7 +21,8 @@ export function doFileGet(uri: string, saveFile: boolean = true) { // set save_file argument to True to save the file (old behaviour) Lbry.get({ uri, save_file: saveFile }) .then((streamInfo: GetResponse) => { - const timeout = streamInfo === null || typeof streamInfo !== 'object'; + const timeout = + streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout'; if (timeout) { dispatch({ @@ -39,8 +40,19 @@ export function doFileGet(uri: string, saveFile: boolean = true) { const { streaming_url: streamingUrl } = streamInfo; dispatch({ type: ACTIONS.PURCHASE_URI_COMPLETED, - data: { uri, streamingUrl: !saveFile && streamingUrl ? streamingUrl : null }, + data: { uri, streamingUrl }, }); + dispatch({ + type: ACTIONS.FETCH_FILE_INFO_COMPLETED, + data: { + fileInfo: streamInfo, + outpoint: streamInfo.outpoint, + }, + }); + + if (onSuccess) { + onSuccess(streamInfo); + } } }) .catch(() => { @@ -63,7 +75,12 @@ export function doFileGet(uri: string, saveFile: boolean = true) { }; } -export function doPurchaseUri(uri: string, costInfo: { cost: number }, saveFile: boolean = true) { +export function doPurchaseUri( + uri: string, + costInfo: { cost: number }, + saveFile: boolean = true, + onSuccess?: GetResponse => any +) { return (dispatch: Dispatch, getState: GetState) => { dispatch({ type: ACTIONS.PURCHASE_URI_STARTED, @@ -98,7 +115,7 @@ export function doPurchaseUri(uri: string, costInfo: { cost: number }, saveFile: return; } - dispatch(doFileGet(uri, saveFile)); + dispatch(doFileGet(uri, saveFile, onSuccess)); }; } diff --git a/src/redux/selectors/file.js b/src/redux/selectors/file.js index 7e0a1a1..3e5b4b8 100644 --- a/src/redux/selectors/file.js +++ b/src/redux/selectors/file.js @@ -1,5 +1,6 @@ // @flow import { createSelector } from 'reselect'; +import { makeSelectFileInfoForUri } from 'redux/selectors/file_info'; type State = { file: FileState }; @@ -31,8 +32,10 @@ export const selectLastPurchasedUri: (state: State) => string = createSelector( state.purchasedUris.length > 0 ? state.purchasedUris[state.purchasedUris.length - 1] : null ); -export const makeSelectStreamingUrlForUri = (uri: string): ((state: State) => {}) => +export const makeSelectStreamingUrlForUri = (uri: string) => createSelector( - selectPurchasedStreamingUrls, - streamingUrls => streamingUrls && streamingUrls[uri] + makeSelectFileInfoForUri(uri), + fileInfo => { + return fileInfo && fileInfo.streaming_url; + } ); diff --git a/src/redux/selectors/file_info.js b/src/redux/selectors/file_info.js index 7c045fe..7454209 100644 --- a/src/redux/selectors/file_info.js +++ b/src/redux/selectors/file_info.js @@ -3,9 +3,11 @@ import { selectIsFetchingClaimListMine, selectMyClaims, selectClaimsById, + makeSelectContentTypeForUri, } from 'redux/selectors/claims'; import { createSelector } from 'reselect'; import { buildURI } from 'lbryURI'; +import Lbry from 'lbry'; export const selectState = state => state.fileInfo || {}; @@ -72,7 +74,7 @@ export const selectFileInfosDownloaded = createSelector( return ( fileInfo && myClaimIds.indexOf(fileInfo.claim_id) === -1 && - (fileInfo.completed || fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0 ) + (fileInfo.completed || fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0) ); }) ); @@ -238,3 +240,41 @@ export const selectDownloadedUris = createSelector( .reverse() .map(claim => `lbry://${claim.claim_name}#${claim.claim_id}`) ); + +export const makeSelectMediaTypeForUri = (uri: string) => + createSelector( + makeSelectFileInfoForUri(uri), + makeSelectContentTypeForUri(uri), + (fileInfo, contentType) => { + if (!fileInfo && !contentType) { + return undefined; + } + + const fileName = fileInfo && fileInfo.file_name; + return Lbry.getMediaType(contentType, fileName); + } + ); + +export const makeSelectUriIsStreamable = (uri: string) => + createSelector( + makeSelectMediaTypeForUri(uri), + mediaType => { + const isStreamable = ['audio', 'video', 'image'].indexOf(mediaType) !== -1; + return isStreamable; + } + ); + +export const makeSelectDownloadPathForUri = (uri: string) => + createSelector( + makeSelectFileInfoForUri(uri), + fileInfo => { + return fileInfo && fileInfo.download_path; + } + ); +export const makeSelectFileNameForUri = (uri: string) => + createSelector( + makeSelectFileInfoForUri(uri), + fileInfo => { + return fileInfo && fileInfo.file_name; + } + ); diff --git a/yarn.lock b/yarn.lock index 49dc513..182afdc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3523,6 +3523,11 @@ mime-types@^2.1.12, mime-types@~2.1.17: dependencies: mime-db "~1.33.0" +mime@^2.4.4: + version "2.4.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" + integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== + mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" -- 2.45.3 From c27c6ba6150a1fa30d874a678af94b116041f557 Mon Sep 17 00:00:00 2001 From: jessop Date: Mon, 5 Aug 2019 17:27:14 -0400 Subject: [PATCH 3/6] dont crash --- dist/bundle.es.js | 2 +- src/redux/selectors/claims.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index c138c15..14e4c16 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -1533,7 +1533,7 @@ const makeSelectRecommendedContentForUri = uri => reselect.createSelector(makeSe const { title } = claim.value; - const searchQuery = getSearchQueryString(title.replace(/\//, ' ')); + const searchQuery = getSearchQueryString(title ? title.replace(/\//, ' ') : ''); let searchUris = searchUrisByQuery[searchQuery]; if (searchUris) { diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index 7c477dc..eac3390 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -223,8 +223,8 @@ export const makeSelectDateForUri = (uri: string) => (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta.creation_timestamp - ? claim.meta.creation_timestamp * 1000 - : null); + ? claim.meta.creation_timestamp * 1000 + : null); if (!timestamp) { return undefined; } @@ -456,7 +456,7 @@ export const makeSelectRecommendedContentForUri = (uri: string) => const { title } = claim.value; - const searchQuery = getSearchQueryString(title.replace(/\//, ' ')); + const searchQuery = getSearchQueryString(title ? title.replace(/\//, ' ') : ''); let searchUris = searchUrisByQuery[searchQuery]; if (searchUris) { -- 2.45.3 From fe66fae040e6e5f07b726af946d46540f4babc8e Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Mon, 5 Aug 2019 22:52:46 -0400 Subject: [PATCH 4/6] remove purchasedStreamingUrls --- dist/bundle.es.js | 36 +++++++---------------------------- dist/flow-typed/File.js | 5 ++--- dist/flow-typed/mime.js | 4 ++++ flow-typed/File.js | 5 ++--- flow-typed/mime.js | 4 ++++ src/constants/action_types.js | 3 --- src/index.js | 1 - src/lbry.js | 5 ++++- src/redux/actions/file.js | 13 ++----------- src/redux/reducers/file.js | 8 +------- src/redux/selectors/file.js | 5 ----- 11 files changed, 26 insertions(+), 63 deletions(-) create mode 100644 dist/flow-typed/mime.js create mode 100644 flow-typed/mime.js diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 2177543..568ff79 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -153,9 +153,6 @@ const PURCHASE_URI_STARTED = 'PURCHASE_URI_STARTED'; const PURCHASE_URI_COMPLETED = 'PURCHASE_URI_COMPLETED'; const PURCHASE_URI_FAILED = 'PURCHASE_URI_FAILED'; const DELETE_PURCHASED_URI = 'DELETE_PURCHASED_URI'; -const LOADING_FILE_STARTED = 'LOADING_FILE_STARTED'; -const LOADING_FILE_COMPLETED = 'LOADING_FILE_COMPLETED'; -const LOADING_FILE_FAILED = 'LOADING_FILE_FAILED'; // Search const SEARCH_START = 'SEARCH_START'; @@ -382,9 +379,6 @@ var action_types = /*#__PURE__*/Object.freeze({ PURCHASE_URI_COMPLETED: PURCHASE_URI_COMPLETED, PURCHASE_URI_FAILED: PURCHASE_URI_FAILED, DELETE_PURCHASED_URI: DELETE_PURCHASED_URI, - LOADING_FILE_STARTED: LOADING_FILE_STARTED, - LOADING_FILE_COMPLETED: LOADING_FILE_COMPLETED, - LOADING_FILE_FAILED: LOADING_FILE_FAILED, SEARCH_START: SEARCH_START, SEARCH_SUCCESS: SEARCH_SUCCESS, SEARCH_FAIL: SEARCH_FAIL, @@ -717,8 +711,10 @@ const Lbry = { // Get mediaType from contentType if (contentType) { - return (/^[^/]+/.exec(contentType)[0] - ); + const matches = /^[^/]+/.exec(contentType); + if (matches) { + return matches[0]; + } } return 'unknown'; @@ -2625,8 +2621,6 @@ const selectFailedPurchaseUris = reselect.createSelector(selectState$4, state => const selectPurchasedUris = reselect.createSelector(selectState$4, state => state.purchasedUris); -const selectPurchasedStreamingUrls = reselect.createSelector(selectState$4, state => state.purchasedStreamingUrls); - const selectLastPurchasedUri = reselect.createSelector(selectState$4, state => state.purchasedUris.length > 0 ? state.purchasedUris[state.purchasedUris.length - 1] : null); const makeSelectStreamingUrlForUri = uri => reselect.createSelector(makeSelectFileInfoForUri(uri), fileInfo => { @@ -2638,7 +2632,7 @@ const makeSelectStreamingUrlForUri = uri => reselect.createSelector(makeSelectFi function doFileGet(uri, saveFile = true, onSuccess) { return dispatch => { dispatch({ - type: LOADING_FILE_STARTED, + type: PURCHASE_URI_STARTED, data: { uri } @@ -2649,10 +2643,6 @@ function doFileGet(uri, saveFile = true, onSuccess) { const timeout = streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout'; if (timeout) { - dispatch({ - type: LOADING_FILE_FAILED, - data: { uri } - }); dispatch({ type: PURCHASE_URI_FAILED, data: { uri } @@ -2661,10 +2651,9 @@ function doFileGet(uri, saveFile = true, onSuccess) { dispatch(doToast({ message: `File timeout for uri ${uri}`, isError: true })); } else { // purchase was completed successfully - const { streaming_url: streamingUrl } = streamInfo; dispatch({ type: PURCHASE_URI_COMPLETED, - data: { uri, streamingUrl } + data: { uri } }); dispatch({ type: FETCH_FILE_INFO_COMPLETED, @@ -2679,10 +2668,6 @@ function doFileGet(uri, saveFile = true, onSuccess) { } } }).catch(() => { - dispatch({ - type: LOADING_FILE_FAILED, - data: { uri } - }); dispatch({ type: PURCHASE_URI_FAILED, data: { uri } @@ -4060,7 +4045,6 @@ const reducers$3 = {}; const defaultState$4 = { failedPurchaseUris: [], purchasedUris: [], - purchasedStreamingUrls: {}, purchaseUriErrorMessage: '' }; @@ -4078,10 +4062,9 @@ reducers$3[PURCHASE_URI_STARTED] = (state, action) => { }; reducers$3[PURCHASE_URI_COMPLETED] = (state, action) => { - const { uri, streamingUrl } = action.data; + const { uri } = action.data; const newPurchasedUris = state.purchasedUris.slice(); const newFailedPurchaseUris = state.failedPurchaseUris.slice(); - const newPurchasedStreamingUrls = Object.assign({}, state.purchasedStreamingUrls); if (!newPurchasedUris.includes(uri)) { newPurchasedUris.push(uri); @@ -4089,14 +4072,10 @@ reducers$3[PURCHASE_URI_COMPLETED] = (state, action) => { if (newFailedPurchaseUris.includes(uri)) { newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1); } - if (streamingUrl) { - newPurchasedStreamingUrls[uri] = streamingUrl; - } return _extends$9({}, state, { failedPurchaseUris: newFailedPurchaseUris, purchasedUris: newPurchasedUris, - purchasedStreamingUrls: newPurchasedStreamingUrls, purchaseUriErrorMessage: '' }); }; @@ -4976,7 +4955,6 @@ exports.selectPendingClaims = selectPendingClaims; exports.selectPlayingUri = selectPlayingUri; exports.selectPublishFormValues = selectPublishFormValues; exports.selectPurchaseUriErrorMessage = selectPurchaseUriErrorMessage; -exports.selectPurchasedStreamingUrls = selectPurchasedStreamingUrls; exports.selectPurchasedUris = selectPurchasedUris; exports.selectReceiveAddress = selectReceiveAddress; exports.selectRecentTransactions = selectRecentTransactions; diff --git a/dist/flow-typed/File.js b/dist/flow-typed/File.js index 42c9b16..c4c151c 100644 --- a/dist/flow-typed/File.js +++ b/dist/flow-typed/File.js @@ -38,7 +38,6 @@ declare type FileListItem = { declare type FileState = { failedPurchaseUris: Array, purchasedUris: Array, - purchasedStreamingUrls: {}, }; declare type PurchaseUriCompleted = { @@ -53,7 +52,7 @@ declare type PurchaseUriFailed = { type: ACTIONS.PURCHASE_URI_FAILED, data: { uri: string, - error: any + error: any, }, }; @@ -68,6 +67,6 @@ declare type PurchaseUriStarted = { declare type DeletePurchasedUri = { type: ACTIONS.DELETE_PURCHASED_URI, data: { - uri: string + uri: string, }, }; diff --git a/dist/flow-typed/mime.js b/dist/flow-typed/mime.js new file mode 100644 index 0000000..476b179 --- /dev/null +++ b/dist/flow-typed/mime.js @@ -0,0 +1,4 @@ +// @flow +declare module 'mime' { + declare module.exports: any; +} diff --git a/flow-typed/File.js b/flow-typed/File.js index 42c9b16..c4c151c 100644 --- a/flow-typed/File.js +++ b/flow-typed/File.js @@ -38,7 +38,6 @@ declare type FileListItem = { declare type FileState = { failedPurchaseUris: Array, purchasedUris: Array, - purchasedStreamingUrls: {}, }; declare type PurchaseUriCompleted = { @@ -53,7 +52,7 @@ declare type PurchaseUriFailed = { type: ACTIONS.PURCHASE_URI_FAILED, data: { uri: string, - error: any + error: any, }, }; @@ -68,6 +67,6 @@ declare type PurchaseUriStarted = { declare type DeletePurchasedUri = { type: ACTIONS.DELETE_PURCHASED_URI, data: { - uri: string + uri: string, }, }; diff --git a/flow-typed/mime.js b/flow-typed/mime.js new file mode 100644 index 0000000..476b179 --- /dev/null +++ b/flow-typed/mime.js @@ -0,0 +1,4 @@ +// @flow +declare module 'mime' { + declare module.exports: any; +} diff --git a/src/constants/action_types.js b/src/constants/action_types.js index b75997b..4b07603 100644 --- a/src/constants/action_types.js +++ b/src/constants/action_types.js @@ -127,9 +127,6 @@ export const PURCHASE_URI_STARTED = 'PURCHASE_URI_STARTED'; export const PURCHASE_URI_COMPLETED = 'PURCHASE_URI_COMPLETED'; export const PURCHASE_URI_FAILED = 'PURCHASE_URI_FAILED'; export const DELETE_PURCHASED_URI = 'DELETE_PURCHASED_URI'; -export const LOADING_FILE_STARTED = 'LOADING_FILE_STARTED'; -export const LOADING_FILE_COMPLETED = 'LOADING_FILE_COMPLETED'; -export const LOADING_FILE_FAILED = 'LOADING_FILE_FAILED'; // Search export const SEARCH_START = 'SEARCH_START'; diff --git a/src/index.js b/src/index.js index 9a5574e..2161100 100644 --- a/src/index.js +++ b/src/index.js @@ -140,7 +140,6 @@ export { selectToast, selectError } from 'redux/selectors/notifications'; export { selectFailedPurchaseUris, selectPurchasedUris, - selectPurchasedStreamingUrls, selectPurchaseUriErrorMessage, selectLastPurchasedUri, makeSelectStreamingUrlForUri, diff --git a/src/lbry.js b/src/lbry.js index 5ceb6dd..b87a8a2 100644 --- a/src/lbry.js +++ b/src/lbry.js @@ -61,7 +61,10 @@ const Lbry: LbryTypes = { // Get mediaType from contentType if (contentType) { - return /^[^/]+/.exec(contentType)[0]; + const matches = /^[^/]+/.exec(contentType); + if (matches) { + return matches[0]; + } } return 'unknown'; diff --git a/src/redux/actions/file.js b/src/redux/actions/file.js index 305ff4f..1697687 100644 --- a/src/redux/actions/file.js +++ b/src/redux/actions/file.js @@ -12,7 +12,7 @@ type GetState = () => { file: FileState }; export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: GetResponse => any) { return (dispatch: Dispatch) => { dispatch({ - type: ACTIONS.LOADING_FILE_STARTED, + type: ACTIONS.PURCHASE_URI_STARTED, data: { uri, }, @@ -25,10 +25,6 @@ export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: Get streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout'; if (timeout) { - dispatch({ - type: ACTIONS.LOADING_FILE_FAILED, - data: { uri }, - }); dispatch({ type: ACTIONS.PURCHASE_URI_FAILED, data: { uri }, @@ -37,10 +33,9 @@ export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: Get dispatch(doToast({ message: `File timeout for uri ${uri}`, isError: true })); } else { // purchase was completed successfully - const { streaming_url: streamingUrl } = streamInfo; dispatch({ type: ACTIONS.PURCHASE_URI_COMPLETED, - data: { uri, streamingUrl }, + data: { uri }, }); dispatch({ type: ACTIONS.FETCH_FILE_INFO_COMPLETED, @@ -56,10 +51,6 @@ export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: Get } }) .catch(() => { - dispatch({ - type: ACTIONS.LOADING_FILE_FAILED, - data: { uri }, - }); dispatch({ type: ACTIONS.PURCHASE_URI_FAILED, data: { uri }, diff --git a/src/redux/reducers/file.js b/src/redux/reducers/file.js index 95a3b7e..0e9a40e 100644 --- a/src/redux/reducers/file.js +++ b/src/redux/reducers/file.js @@ -5,7 +5,6 @@ const reducers = {}; const defaultState = { failedPurchaseUris: [], purchasedUris: [], - purchasedStreamingUrls: {}, purchaseUriErrorMessage: '', }; @@ -30,10 +29,9 @@ reducers[ACTIONS.PURCHASE_URI_COMPLETED] = ( state: FileState, action: PurchaseUriCompleted ): FileState => { - const { uri, streamingUrl } = action.data; + const { uri } = action.data; const newPurchasedUris = state.purchasedUris.slice(); const newFailedPurchaseUris = state.failedPurchaseUris.slice(); - const newPurchasedStreamingUrls = Object.assign({}, state.purchasedStreamingUrls); if (!newPurchasedUris.includes(uri)) { newPurchasedUris.push(uri); @@ -41,15 +39,11 @@ reducers[ACTIONS.PURCHASE_URI_COMPLETED] = ( if (newFailedPurchaseUris.includes(uri)) { newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1); } - if (streamingUrl) { - newPurchasedStreamingUrls[uri] = streamingUrl; - } return { ...state, failedPurchaseUris: newFailedPurchaseUris, purchasedUris: newPurchasedUris, - purchasedStreamingUrls: newPurchasedStreamingUrls, purchaseUriErrorMessage: '', }; }; diff --git a/src/redux/selectors/file.js b/src/redux/selectors/file.js index 3e5b4b8..dbdb0be 100644 --- a/src/redux/selectors/file.js +++ b/src/redux/selectors/file.js @@ -21,11 +21,6 @@ export const selectPurchasedUris: (state: State) => Array = createSelect state => state.purchasedUris ); -export const selectPurchasedStreamingUrls: (state: State) => {} = createSelector( - selectState, - state => state.purchasedStreamingUrls -); - export const selectLastPurchasedUri: (state: State) => string = createSelector( selectState, state => -- 2.45.3 From e10986e8e54d25480ac2b5dd2a31fec8b254471a Mon Sep 17 00:00:00 2001 From: Akinwale Ariwodola Date: Tue, 13 Aug 2019 16:27:32 +0100 Subject: [PATCH 5/6] Mobile updates (#179) * return lowercase tag names for unfollowed tags * fix: thumbnail url * fix claim.meta.creation_timestamp check * track if the last page reached was reached for claim_search queries * fix CLAIM_SEARCH_FAILED reducer --- dist/bundle.es.js | 35 ++++++++++++++++++++++++----------- src/index.js | 1 + src/redux/actions/claims.js | 8 +++++++- src/redux/actions/publish.js | 34 +++++++++++++++++----------------- src/redux/reducers/claims.js | 14 ++++++++++++-- src/redux/selectors/claims.js | 11 ++++++++--- src/redux/selectors/tags.js | 2 +- 7 files changed, 70 insertions(+), 35 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 14e4c16..4626cbb 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -7,8 +7,6 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau require('proxy-polyfill'); var reselect = require('reselect'); var uuid = _interopDefault(require('uuid/v4')); -var fs = _interopDefault(require('fs')); -var path = _interopDefault(require('path')); const MINIMUM_PUBLISH_BID = 0.00000001; @@ -1392,7 +1390,7 @@ const makeSelectMetadataItemForUri = (uri, key) => reselect.createSelector(makeS const makeSelectTitleForUri = uri => reselect.createSelector(makeSelectMetadataForUri(uri), metadata => metadata && metadata.title); const makeSelectDateForUri = uri => reselect.createSelector(makeSelectClaimForUri(uri), claim => { - const timestamp = claim && claim.value && (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta.creation_timestamp ? claim.meta.creation_timestamp * 1000 : null); + const timestamp = claim && claim.value && (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta && claim.meta.creation_timestamp ? claim.meta.creation_timestamp * 1000 : null); if (!timestamp) { return undefined; } @@ -1570,6 +1568,8 @@ const selectFetchingClaimSearch = reselect.createSelector(selectFetchingClaimSea const selectClaimSearchByQuery = reselect.createSelector(selectState$1, state => state.claimSearchByQuery || {}); +const selectClaimSearchByQueryLastPageReached = reselect.createSelector(selectState$1, state => state.claimSearchByQueryLastPageReached || {}); + const makeSelectShortUrlForUri = uri => reselect.createSelector(makeSelectClaimForUri(uri), claim => claim && claim.short_url); const selectState$2 = state => state.wallet || {}; @@ -2403,7 +2403,13 @@ function doClaimSearch(options = { dispatch({ type: CLAIM_SEARCH_COMPLETED, - data: { query, resolveInfo, uris, append: options.page && options.page !== 1 } + data: { + query, + resolveInfo, + uris, + append: options.page && options.page !== 1, + pageSize: options.page_size + } }); }; @@ -2880,7 +2886,7 @@ const doUpdatePublishForm = publishFormValue => dispatch => dispatch({ data: _extends$4({}, publishFormValue) }); -const doUploadThumbnail = (filePath, thumbnailBuffer, fsAdapter) => dispatch => { +const doUploadThumbnail = (filePath, thumbnailBuffer, fsAdapter, fs, path) => dispatch => { let thumbnail, fileExt, fileName, fileType; const makeid = () => { @@ -2925,7 +2931,7 @@ const doUploadThumbnail = (filePath, thumbnailBuffer, fsAdapter) => dispatch => type: UPDATE_PUBLISH_FORM, data: { uploadThumbnailStatus: COMPLETE, - thumbnail: `${json.data.url}${fileExt}` + thumbnail: `${json.data.url}.${fileExt}` } }) : uploadError(json.message)).catch(err => uploadError(err.message)); }); @@ -2963,7 +2969,7 @@ const doUploadThumbnail = (filePath, thumbnailBuffer, fsAdapter) => dispatch => } }; -const doPrepareEdit = (claim, uri, fileInfo) => dispatch => { +const doPrepareEdit = (claim, uri, fileInfo, fs) => dispatch => { const { name, amount, value } = claim; const channelName = claim && claim.signing_channel && claim.signing_channel.normalized_name || null; const { @@ -3017,7 +3023,7 @@ const doPrepareEdit = (claim, uri, fileInfo) => dispatch => { publishData['channel'] = channelName; } - if (fileInfo && fileInfo.download_path) { + if (fs && fileInfo && fileInfo.download_path) { try { fs.accessSync(fileInfo.download_path, fs.constants.R_OK); publishData.filePath = fileInfo.download_path; @@ -3462,6 +3468,7 @@ const defaultState = { pendingById: {}, claimSearchError: false, claimSearchByQuery: {}, + claimSearchByQueryLastPageReached: {}, fetchingClaimSearchByQuery: {} }; @@ -3703,7 +3710,8 @@ reducers[CLAIM_SEARCH_STARTED] = (state, action) => { reducers[CLAIM_SEARCH_COMPLETED] = (state, action) => { const fetchingClaimSearchByQuery = Object.assign({}, state.fetchingClaimSearchByQuery); const claimSearchByQuery = Object.assign({}, state.claimSearchByQuery); - const { append, query, uris } = action.data; + const claimSearchByQueryLastPageReached = Object.assign({}, state.claimSearchByQueryLastPageReached); + const { append, query, uris, pageSize } = action.data; if (append) { // todo: check for duplicate uris when concatenating? @@ -3712,17 +3720,21 @@ reducers[CLAIM_SEARCH_COMPLETED] = (state, action) => { claimSearchByQuery[query] = uris; } + // the returned number of uris is less than the page size, so we're on the last page + claimSearchByQueryLastPageReached[query] = uris.length < pageSize; + delete fetchingClaimSearchByQuery[query]; return Object.assign({}, state, _extends$5({}, handleClaimAction(state, action), { claimSearchByQuery, + claimSearchByQueryLastPageReached, fetchingClaimSearchByQuery })); }; reducers[CLAIM_SEARCH_FAILED] = (state, action) => { const fetchingClaimSearchByQuery = Object.assign({}, state.fetchingClaimSearchByQuery); - fetchingClaimSearchByQuery[action.data.tags] = false; + delete fetchingClaimSearchByQuery[action.data.query]; return Object.assign({}, state, { fetchingClaimSearchByQuery @@ -4724,7 +4736,7 @@ const selectUnfollowedTags = reselect.createSelector(selectKnownTagsByName, sele Object.keys(tagsByName).forEach(key => { if (!followedTagsSet.has(key)) { const { name } = tagsByName[key]; - tagsToReturn.push({ name }); + tagsToReturn.push({ name: name.toLowerCase() }); } }); @@ -4884,6 +4896,7 @@ exports.selectBlocks = selectBlocks; exports.selectChannelClaimCounts = selectChannelClaimCounts; exports.selectChannelIsBlocked = selectChannelIsBlocked; exports.selectClaimSearchByQuery = selectClaimSearchByQuery; +exports.selectClaimSearchByQueryLastPageReached = selectClaimSearchByQueryLastPageReached; exports.selectClaimsById = selectClaimsById; exports.selectClaimsByUri = selectClaimsByUri; exports.selectCurrentChannelPage = selectCurrentChannelPage; diff --git a/src/index.js b/src/index.js index 2f93891..6a3bdc1 100644 --- a/src/index.js +++ b/src/index.js @@ -197,6 +197,7 @@ export { selectFetchingClaimSearch, selectFetchingClaimSearchByQuery, selectClaimSearchByQuery, + selectClaimSearchByQueryLastPageReached, } from 'redux/selectors/claims'; export { makeSelectCommentsForUri } from 'redux/selectors/comments'; diff --git a/src/redux/actions/claims.js b/src/redux/actions/claims.js index 902c87b..0f6e44e 100644 --- a/src/redux/actions/claims.js +++ b/src/redux/actions/claims.js @@ -336,7 +336,13 @@ export function doClaimSearch( dispatch({ type: ACTIONS.CLAIM_SEARCH_COMPLETED, - data: { query, resolveInfo, uris, append: options.page && options.page !== 1 }, + data: { + query, + resolveInfo, + uris, + append: options.page && options.page !== 1, + pageSize: options.page_size, + }, }); }; diff --git a/src/redux/actions/publish.js b/src/redux/actions/publish.js index 38cb9bd..69844c0 100644 --- a/src/redux/actions/publish.js +++ b/src/redux/actions/publish.js @@ -13,8 +13,6 @@ import { selectMyClaimsWithoutChannels, } from 'redux/selectors/claims'; import { selectPublishFormValues, selectMyClaimForUri } from 'redux/selectors/publish'; -import fs from 'fs'; -import path from 'path'; export const doResetThumbnailStatus = () => (dispatch: Dispatch) => { dispatch({ @@ -66,7 +64,9 @@ export const doUpdatePublishForm = (publishFormValue: UpdatePublishFormData) => export const doUploadThumbnail = ( filePath: string, thumbnailBuffer: Uint8Array, - fsAdapter: any + fsAdapter: any, + fs: any, + path: any ) => (dispatch: Dispatch) => { let thumbnail, fileExt, fileName, fileType; @@ -118,12 +118,12 @@ export const doUploadThumbnail = ( .then(json => json.success ? dispatch({ - type: ACTIONS.UPDATE_PUBLISH_FORM, - data: { - uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE, - thumbnail: `${json.data.url}${fileExt}`, - }, - }) + type: ACTIONS.UPDATE_PUBLISH_FORM, + data: { + uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE, + thumbnail: `${json.data.url}.${fileExt}`, + }, + }) : uploadError(json.message) ) .catch(err => uploadError(err.message)); @@ -157,19 +157,19 @@ export const doUploadThumbnail = ( .then(json => json.success ? dispatch({ - type: ACTIONS.UPDATE_PUBLISH_FORM, - data: { - uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE, - thumbnail: `${json.data.url}${fileExt}`, - }, - }) + type: ACTIONS.UPDATE_PUBLISH_FORM, + data: { + uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE, + thumbnail: `${json.data.url}${fileExt}`, + }, + }) : uploadError(json.message) ) .catch(err => uploadError(err.message)); } }; -export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileListItem) => ( +export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileListItem, fs: any) => ( dispatch: Dispatch ) => { const { name, amount, value } = claim; @@ -226,7 +226,7 @@ export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileLis publishData['channel'] = channelName; } - if (fileInfo && fileInfo.download_path) { + if (fs && fileInfo && fileInfo.download_path) { try { fs.accessSync(fileInfo.download_path, fs.constants.R_OK); publishData.filePath = fileInfo.download_path; diff --git a/src/redux/reducers/claims.js b/src/redux/reducers/claims.js index a001d3a..ba94348 100644 --- a/src/redux/reducers/claims.js +++ b/src/redux/reducers/claims.js @@ -23,6 +23,7 @@ type State = { fetchingMyChannels: boolean, fetchingClaimSearchByQuery: { [string]: boolean }, claimSearchByQuery: { [string]: Array }, + claimSearchByQueryLastPageReached: { [string]: Array }, claimsByChannel: { [string]: { all: Array, @@ -47,6 +48,7 @@ const defaultState = { pendingById: {}, claimSearchError: false, claimSearchByQuery: {}, + claimSearchByQueryLastPageReached: {}, fetchingClaimSearchByQuery: {}, }; @@ -299,7 +301,11 @@ reducers[ACTIONS.CLAIM_SEARCH_STARTED] = (state: State, action: any): State => { reducers[ACTIONS.CLAIM_SEARCH_COMPLETED] = (state: State, action: any): State => { const fetchingClaimSearchByQuery = Object.assign({}, state.fetchingClaimSearchByQuery); const claimSearchByQuery = Object.assign({}, state.claimSearchByQuery); - const { append, query, uris } = action.data; + const claimSearchByQueryLastPageReached = Object.assign( + {}, + state.claimSearchByQueryLastPageReached + ); + const { append, query, uris, pageSize } = action.data; if (append) { // todo: check for duplicate uris when concatenating? @@ -311,18 +317,22 @@ reducers[ACTIONS.CLAIM_SEARCH_COMPLETED] = (state: State, action: any): State => claimSearchByQuery[query] = uris; } + // the returned number of uris is less than the page size, so we're on the last page + claimSearchByQueryLastPageReached[query] = uris.length < pageSize; + delete fetchingClaimSearchByQuery[query]; return Object.assign({}, state, { ...handleClaimAction(state, action), claimSearchByQuery, + claimSearchByQueryLastPageReached, fetchingClaimSearchByQuery, }); }; reducers[ACTIONS.CLAIM_SEARCH_FAILED] = (state: State, action: any): State => { const fetchingClaimSearchByQuery = Object.assign({}, state.fetchingClaimSearchByQuery); - fetchingClaimSearchByQuery[action.data.tags] = false; + delete fetchingClaimSearchByQuery[action.data.query]; return Object.assign({}, state, { fetchingClaimSearchByQuery, diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index eac3390..896fb76 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -222,9 +222,9 @@ export const makeSelectDateForUri = (uri: string) => claim.value && (claim.value.release_time ? claim.value.release_time * 1000 - : claim.meta.creation_timestamp - ? claim.meta.creation_timestamp * 1000 - : null); + : claim.meta && claim.meta.creation_timestamp + ? claim.meta.creation_timestamp * 1000 + : null); if (!timestamp) { return undefined; } @@ -515,6 +515,11 @@ export const selectClaimSearchByQuery = createSelector( state => state.claimSearchByQuery || {} ); +export const selectClaimSearchByQueryLastPageReached = createSelector( + selectState, + state => state.claimSearchByQueryLastPageReached || {} +); + export const makeSelectClaimSearchUrisByOptions = (options: {}) => createSelector( selectClaimSearchByQuery, diff --git a/src/redux/selectors/tags.js b/src/redux/selectors/tags.js index d38d375..ec805a0 100644 --- a/src/redux/selectors/tags.js +++ b/src/redux/selectors/tags.js @@ -29,7 +29,7 @@ export const selectUnfollowedTags = createSelector( Object.keys(tagsByName).forEach(key => { if (!followedTagsSet.has(key)) { const { name } = tagsByName[key]; - tagsToReturn.push({ name }); + tagsToReturn.push({ name: name.toLowerCase() }); } }); -- 2.45.3 From 291b06864261c97d1c8be228ee86191ead537612 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Tue, 13 Aug 2019 13:33:32 -0400 Subject: [PATCH 6/6] use FETCH_FILE_INFO_XXX in favor of LOADING_URI_XXX --- dist/bundle.es.js | 230 +++++++++++++++----------------- src/constants/action_types.js | 1 + src/redux/actions/file.js | 20 ++- src/redux/reducers/file_info.js | 45 ++----- 4 files changed, 133 insertions(+), 163 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 568ff79..35d2b55 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -137,6 +137,7 @@ const FILE_LIST_STARTED = 'FILE_LIST_STARTED'; const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED'; const FETCH_FILE_INFO_STARTED = 'FETCH_FILE_INFO_STARTED'; const FETCH_FILE_INFO_COMPLETED = 'FETCH_FILE_INFO_COMPLETED'; +const FETCH_FILE_INFO_FAILED = 'FETCH_FILE_INFO_FAILED'; const LOADING_VIDEO_STARTED = 'LOADING_VIDEO_STARTED'; const LOADING_VIDEO_COMPLETED = 'LOADING_VIDEO_COMPLETED'; const LOADING_VIDEO_FAILED = 'LOADING_VIDEO_FAILED'; @@ -363,6 +364,7 @@ var action_types = /*#__PURE__*/Object.freeze({ FILE_LIST_SUCCEEDED: FILE_LIST_SUCCEEDED, FETCH_FILE_INFO_STARTED: FETCH_FILE_INFO_STARTED, FETCH_FILE_INFO_COMPLETED: FETCH_FILE_INFO_COMPLETED, + FETCH_FILE_INFO_FAILED: FETCH_FILE_INFO_FAILED, LOADING_VIDEO_STARTED: LOADING_VIDEO_STARTED, LOADING_VIDEO_COMPLETED: LOADING_VIDEO_COMPLETED, LOADING_VIDEO_FAILED: LOADING_VIDEO_FAILED, @@ -2630,11 +2632,15 @@ const makeSelectStreamingUrlForUri = uri => reselect.createSelector(makeSelectFi // function doFileGet(uri, saveFile = true, onSuccess) { - return dispatch => { + return (dispatch, getState) => { + const state = getState(); + const { nout, txid } = makeSelectClaimForUri(uri)(state); + const outpoint = `${txid}:${nout}`; + dispatch({ - type: PURCHASE_URI_STARTED, + type: FETCH_FILE_INFO_STARTED, data: { - uri + outpoint } }); @@ -2644,8 +2650,8 @@ function doFileGet(uri, saveFile = true, onSuccess) { if (timeout) { dispatch({ - type: PURCHASE_URI_FAILED, - data: { uri } + type: FETCH_FILE_INFO_FAILED, + data: { outpoint } }); dispatch(doToast({ message: `File timeout for uri ${uri}`, isError: true })); @@ -2673,6 +2679,11 @@ function doFileGet(uri, saveFile = true, onSuccess) { data: { uri } }); + dispatch({ + type: FETCH_FILE_INFO_FAILED, + data: { outpoint } + }); + dispatch(doToast({ message: `Failed to view ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`, isError: true @@ -3858,8 +3869,6 @@ function contentReducer(state = defaultState$2, action) { return state; } -var _extends$8 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - const reducers$2 = {}; const defaultState$3 = { fileListPublishedSort: DATE_NEW, @@ -3914,20 +3923,27 @@ reducers$2[FETCH_FILE_INFO_COMPLETED] = (state, action) => { }); }; +reducers$2[FETCH_FILE_INFO_FAILED] = (state, action) => { + const { outpoint } = action.data; + const newFetching = Object.assign({}, state.fetching); + delete newFetching[outpoint]; + + return Object.assign({}, state, { + fetching: newFetching + }); +}; + reducers$2[DOWNLOADING_STARTED] = (state, action) => { const { uri, outpoint, fileInfo } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); const newDownloading = Object.assign({}, state.downloadingByOutpoint); - const newLoading = Object.assign({}, state.urisLoading); newDownloading[outpoint] = true; newByOutpoint[outpoint] = fileInfo; - delete newLoading[uri]; return Object.assign({}, state, { downloadingByOutpoint: newDownloading, - urisLoading: newLoading, byOutpoint: newByOutpoint }); }; @@ -3952,11 +3968,9 @@ reducers$2[DOWNLOADING_CANCELED] = (state, action) => { const newDownloading = Object.assign({}, state.downloadingByOutpoint); delete newDownloading[outpoint]; - delete newLoading[uri]; return Object.assign({}, state, { - downloadingByOutpoint: newDownloading, - urisLoading: newLoading + downloadingByOutpoint: newDownloading }); }; @@ -3990,36 +4004,6 @@ reducers$2[FILE_DELETE] = (state, action) => { }); }; -reducers$2[LOADING_VIDEO_STARTED] = (state, action) => { - const { uri } = action.data; - - const newLoading = Object.assign({}, state.urisLoading); - newLoading[uri] = true; - - const newErrors = _extends$8({}, state.errors); - if (uri in newErrors) delete newErrors[uri]; - - return Object.assign({}, state, { - urisLoading: newLoading, - errors: _extends$8({}, newErrors) - }); -}; - -reducers$2[LOADING_VIDEO_FAILED] = (state, action) => { - const { uri } = action.data; - - const newLoading = Object.assign({}, state.urisLoading); - delete newLoading[uri]; - - const newErrors = _extends$8({}, state.errors); - newErrors[uri] = true; - - return Object.assign({}, state, { - urisLoading: newLoading, - errors: _extends$8({}, newErrors) - }); -}; - reducers$2[SET_FILE_LIST_SORT] = (state, action) => { const pageSortStates = { [PUBLISHED]: 'fileListPublishedSort', @@ -4039,7 +4023,7 @@ function fileInfoReducer(state = defaultState$3, action) { return state; } -var _extends$9 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +var _extends$8 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; const reducers$3 = {}; const defaultState$4 = { @@ -4055,7 +4039,7 @@ reducers$3[PURCHASE_URI_STARTED] = (state, action) => { newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1); } - return _extends$9({}, state, { + return _extends$8({}, state, { failedPurchaseUris: newFailedPurchaseUris, purchaseUriErrorMessage: '' }); @@ -4073,7 +4057,7 @@ reducers$3[PURCHASE_URI_COMPLETED] = (state, action) => { newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1); } - return _extends$9({}, state, { + return _extends$8({}, state, { failedPurchaseUris: newFailedPurchaseUris, purchasedUris: newPurchasedUris, purchaseUriErrorMessage: '' @@ -4088,7 +4072,7 @@ reducers$3[PURCHASE_URI_FAILED] = (state, action) => { newFailedPurchaseUris.push(uri); } - return _extends$9({}, state, { + return _extends$8({}, state, { failedPurchaseUris: newFailedPurchaseUris, purchaseUriErrorMessage: error }); @@ -4101,7 +4085,7 @@ reducers$3[DELETE_PURCHASED_URI] = (state, action) => { newPurchasedUris.splice(newPurchasedUris.indexOf(uri), 1); } - return _extends$9({}, state, { + return _extends$8({}, state, { purchasedUris: newPurchasedUris }); }; @@ -4112,7 +4096,7 @@ function fileReducer(state = defaultState$4, action) { return state; } -var _extends$a = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +var _extends$9 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; const defaultState$5 = { notifications: [], @@ -4127,7 +4111,7 @@ const notificationsReducer = handleActions({ const newToasts = state.toasts.slice(); newToasts.push(toast); - return _extends$a({}, state, { + return _extends$9({}, state, { toasts: newToasts }); }, @@ -4135,7 +4119,7 @@ const notificationsReducer = handleActions({ const newToasts = state.toasts.slice(); newToasts.shift(); - return _extends$a({}, state, { + return _extends$9({}, state, { toasts: newToasts }); }, @@ -4146,7 +4130,7 @@ const notificationsReducer = handleActions({ const newNotifications = state.notifications.slice(); newNotifications.push(notification); - return _extends$a({}, state, { + return _extends$9({}, state, { notifications: newNotifications }); }, @@ -4157,7 +4141,7 @@ const notificationsReducer = handleActions({ notifications = notifications.map(pastNotification => pastNotification.id === notification.id ? notification : pastNotification); - return _extends$a({}, state, { + return _extends$9({}, state, { notifications }); }, @@ -4166,7 +4150,7 @@ const notificationsReducer = handleActions({ let newNotifications = state.notifications.slice(); newNotifications = newNotifications.filter(notification => notification.id !== id); - return _extends$a({}, state, { + return _extends$9({}, state, { notifications: newNotifications }); }, @@ -4177,7 +4161,7 @@ const notificationsReducer = handleActions({ const newErrors = state.errors.slice(); newErrors.push(error); - return _extends$a({}, state, { + return _extends$9({}, state, { errors: newErrors }); }, @@ -4185,13 +4169,13 @@ const notificationsReducer = handleActions({ const newErrors = state.errors.slice(); newErrors.shift(); - return _extends$a({}, state, { + return _extends$9({}, state, { errors: newErrors }); } }, defaultState$5); -var _extends$b = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +var _extends$a = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _objectWithoutProperties$2(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } @@ -4228,17 +4212,17 @@ const defaultState$6 = { const publishReducer = handleActions({ [UPDATE_PUBLISH_FORM]: (state, action) => { const { data } = action; - return _extends$b({}, state, data); + return _extends$a({}, state, data); }, - [CLEAR_PUBLISH]: () => _extends$b({}, defaultState$6), - [PUBLISH_START]: state => _extends$b({}, state, { + [CLEAR_PUBLISH]: () => _extends$a({}, defaultState$6), + [PUBLISH_START]: state => _extends$a({}, state, { publishing: true, publishSuccess: false }), - [PUBLISH_FAIL]: state => _extends$b({}, state, { + [PUBLISH_FAIL]: state => _extends$a({}, state, { publishing: false }), - [PUBLISH_SUCCESS]: state => _extends$b({}, state, { + [PUBLISH_SUCCESS]: state => _extends$a({}, state, { publishing: false, publishSuccess: true }), @@ -4253,14 +4237,14 @@ const publishReducer = handleActions({ contentName: name }); - return _extends$b({}, defaultState$6, publishData, { + return _extends$a({}, defaultState$6, publishData, { editingURI: uri, uri: shortUri }); } }, defaultState$6); -var _extends$c = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +var _extends$b = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; const defaultState$7 = { isActive: false, // does the user have any typed text in the search input @@ -4280,29 +4264,29 @@ const defaultState$7 = { }; const searchReducer = handleActions({ - [SEARCH_START]: state => _extends$c({}, state, { + [SEARCH_START]: state => _extends$b({}, state, { searching: true }), [SEARCH_SUCCESS]: (state, action) => { const { query, uris } = action.data; - return _extends$c({}, state, { + return _extends$b({}, state, { searching: false, urisByQuery: Object.assign({}, state.urisByQuery, { [query]: uris }) }); }, - [SEARCH_FAIL]: state => _extends$c({}, state, { + [SEARCH_FAIL]: state => _extends$b({}, state, { searching: false }), - [UPDATE_SEARCH_QUERY]: (state, action) => _extends$c({}, state, { + [UPDATE_SEARCH_QUERY]: (state, action) => _extends$b({}, state, { searchQuery: action.data.query, isActive: true }), - [UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$c({}, state, { - suggestions: _extends$c({}, state.suggestions, { + [UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$b({}, state, { + suggestions: _extends$b({}, state.suggestions, { [action.data.query]: action.data.suggestions }) }), @@ -4310,30 +4294,30 @@ const searchReducer = handleActions({ // sets isActive to false so the uri will be populated correctly if the // user is on a file page. The search query will still be present on any // other page - [DISMISS_NOTIFICATION]: state => _extends$c({}, state, { + [DISMISS_NOTIFICATION]: state => _extends$b({}, state, { isActive: false }), - [SEARCH_FOCUS]: state => _extends$c({}, state, { + [SEARCH_FOCUS]: state => _extends$b({}, state, { focused: true }), - [SEARCH_BLUR]: state => _extends$c({}, state, { + [SEARCH_BLUR]: state => _extends$b({}, state, { focused: false }), [UPDATE_SEARCH_OPTIONS]: (state, action) => { const { options: oldOptions } = state; const newOptions = action.data; - const options = _extends$c({}, oldOptions, newOptions); - return _extends$c({}, state, { + const options = _extends$b({}, oldOptions, newOptions); + return _extends$b({}, state, { options }); } }, defaultState$7); -var _extends$d = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +var _extends$c = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function getDefaultKnownTags() { - return DEFAULT_FOLLOWED_TAGS.concat(DEFAULT_KNOWN_TAGS).reduce((tagsMap, tag) => _extends$d({}, tagsMap, { + return DEFAULT_FOLLOWED_TAGS.concat(DEFAULT_KNOWN_TAGS).reduce((tagsMap, tag) => _extends$c({}, tagsMap, { [tag]: { name: tag } }), {}); } @@ -4356,7 +4340,7 @@ const tagsReducer = handleActions({ newFollowedTags.push(name); } - return _extends$d({}, state, { + return _extends$c({}, state, { followedTags: newFollowedTags }); }, @@ -4365,10 +4349,10 @@ const tagsReducer = handleActions({ const { knownTags } = state; const { name } = action.data; - let newKnownTags = _extends$d({}, knownTags); + let newKnownTags = _extends$c({}, knownTags); newKnownTags[name] = { name }; - return _extends$d({}, state, { + return _extends$c({}, state, { knownTags: newKnownTags }); }, @@ -4377,11 +4361,11 @@ const tagsReducer = handleActions({ const { knownTags, followedTags } = state; const { name } = action.data; - let newKnownTags = _extends$d({}, knownTags); + let newKnownTags = _extends$c({}, knownTags); delete newKnownTags[name]; const newFollowedTags = followedTags.filter(tag => tag !== name); - return _extends$d({}, state, { + return _extends$c({}, state, { knownTags: newKnownTags, followedTags: newFollowedTags }); @@ -4412,7 +4396,7 @@ const blockedReducer = handleActions({ } }, defaultState$9); -var _extends$e = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +var _extends$d = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; const buildDraftTransaction = () => ({ amount: undefined, @@ -4452,25 +4436,25 @@ const defaultState$a = { }; const walletReducer = handleActions({ - [FETCH_TRANSACTIONS_STARTED]: state => _extends$e({}, state, { + [FETCH_TRANSACTIONS_STARTED]: state => _extends$d({}, state, { fetchingTransactions: true }), [FETCH_TRANSACTIONS_COMPLETED]: (state, action) => { - const byId = _extends$e({}, state.transactions); + const byId = _extends$d({}, state.transactions); const { transactions } = action.data; transactions.forEach(transaction => { byId[transaction.txid] = transaction; }); - return _extends$e({}, state, { + return _extends$d({}, state, { transactions: byId, fetchingTransactions: false }); }, - [FETCH_SUPPORTS_STARTED]: state => _extends$e({}, state, { + [FETCH_SUPPORTS_STARTED]: state => _extends$d({}, state, { fetchingSupports: true }), @@ -4483,7 +4467,7 @@ const walletReducer = handleActions({ byOutpoint[`${txid}:${nout}`] = transaction; }); - return _extends$e({}, state, { supports: byOutpoint, fetchingSupports: false }); + return _extends$d({}, state, { supports: byOutpoint, fetchingSupports: false }); }, [ABANDON_SUPPORT_STARTED]: (state, action) => { @@ -4492,7 +4476,7 @@ const walletReducer = handleActions({ currentlyAbandoning[outpoint] = true; - return _extends$e({}, state, { + return _extends$d({}, state, { abandoningSupportsByOutpoint: currentlyAbandoning }); }, @@ -4505,56 +4489,56 @@ const walletReducer = handleActions({ delete currentlyAbandoning[outpoint]; delete byOutpoint[outpoint]; - return _extends$e({}, state, { + return _extends$d({}, state, { supports: byOutpoint, abandoningSupportsById: currentlyAbandoning }); }, - [GET_NEW_ADDRESS_STARTED]: state => _extends$e({}, state, { + [GET_NEW_ADDRESS_STARTED]: state => _extends$d({}, state, { gettingNewAddress: true }), [GET_NEW_ADDRESS_COMPLETED]: (state, action) => { const { address } = action.data; - return _extends$e({}, state, { gettingNewAddress: false, receiveAddress: address }); + return _extends$d({}, state, { gettingNewAddress: false, receiveAddress: address }); }, - [UPDATE_BALANCE]: (state, action) => _extends$e({}, state, { + [UPDATE_BALANCE]: (state, action) => _extends$d({}, state, { balance: action.data.balance }), - [UPDATE_TOTAL_BALANCE]: (state, action) => _extends$e({}, state, { + [UPDATE_TOTAL_BALANCE]: (state, action) => _extends$d({}, state, { totalBalance: action.data.totalBalance }), - [CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$e({}, state, { + [CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$d({}, state, { checkingAddressOwnership: true }), - [CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$e({}, state, { + [CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$d({}, state, { checkingAddressOwnership: false }), [SET_DRAFT_TRANSACTION_AMOUNT]: (state, action) => { const oldDraft = state.draftTransaction; - const newDraft = _extends$e({}, oldDraft, { amount: parseFloat(action.data.amount) }); + const newDraft = _extends$d({}, oldDraft, { amount: parseFloat(action.data.amount) }); - return _extends$e({}, state, { draftTransaction: newDraft }); + return _extends$d({}, state, { draftTransaction: newDraft }); }, [SET_DRAFT_TRANSACTION_ADDRESS]: (state, action) => { const oldDraft = state.draftTransaction; - const newDraft = _extends$e({}, oldDraft, { address: action.data.address }); + const newDraft = _extends$d({}, oldDraft, { address: action.data.address }); - return _extends$e({}, state, { draftTransaction: newDraft }); + return _extends$d({}, state, { draftTransaction: newDraft }); }, [SEND_TRANSACTION_STARTED]: state => { - const newDraftTransaction = _extends$e({}, state.draftTransaction, { sending: true }); + const newDraftTransaction = _extends$d({}, state.draftTransaction, { sending: true }); - return _extends$e({}, state, { draftTransaction: newDraftTransaction }); + return _extends$d({}, state, { draftTransaction: newDraftTransaction }); }, [SEND_TRANSACTION_COMPLETED]: state => Object.assign({}, state, { @@ -4567,103 +4551,103 @@ const walletReducer = handleActions({ error: action.data.error }); - return _extends$e({}, state, { draftTransaction: newDraftTransaction }); + return _extends$d({}, state, { draftTransaction: newDraftTransaction }); }, - [SUPPORT_TRANSACTION_STARTED]: state => _extends$e({}, state, { + [SUPPORT_TRANSACTION_STARTED]: state => _extends$d({}, state, { sendingSupport: true }), - [SUPPORT_TRANSACTION_COMPLETED]: state => _extends$e({}, state, { + [SUPPORT_TRANSACTION_COMPLETED]: state => _extends$d({}, state, { sendingSupport: false }), - [SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$e({}, state, { + [SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$d({}, state, { error: action.data.error, sendingSupport: false }), - [WALLET_STATUS_COMPLETED]: (state, action) => _extends$e({}, state, { + [WALLET_STATUS_COMPLETED]: (state, action) => _extends$d({}, state, { walletIsEncrypted: action.result }), - [WALLET_ENCRYPT_START]: state => _extends$e({}, state, { + [WALLET_ENCRYPT_START]: state => _extends$d({}, state, { walletEncryptPending: true, walletEncryptSucceded: null, walletEncryptResult: null }), - [WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$e({}, state, { + [WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$d({}, state, { walletEncryptPending: false, walletEncryptSucceded: true, walletEncryptResult: action.result }), - [WALLET_ENCRYPT_FAILED]: (state, action) => _extends$e({}, state, { + [WALLET_ENCRYPT_FAILED]: (state, action) => _extends$d({}, state, { walletEncryptPending: false, walletEncryptSucceded: false, walletEncryptResult: action.result }), - [WALLET_DECRYPT_START]: state => _extends$e({}, state, { + [WALLET_DECRYPT_START]: state => _extends$d({}, state, { walletDecryptPending: true, walletDecryptSucceded: null, walletDecryptResult: null }), - [WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$e({}, state, { + [WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$d({}, state, { walletDecryptPending: false, walletDecryptSucceded: true, walletDecryptResult: action.result }), - [WALLET_DECRYPT_FAILED]: (state, action) => _extends$e({}, state, { + [WALLET_DECRYPT_FAILED]: (state, action) => _extends$d({}, state, { walletDecryptPending: false, walletDecryptSucceded: false, walletDecryptResult: action.result }), - [WALLET_UNLOCK_START]: state => _extends$e({}, state, { + [WALLET_UNLOCK_START]: state => _extends$d({}, state, { walletUnlockPending: true, walletUnlockSucceded: null, walletUnlockResult: null }), - [WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$e({}, state, { + [WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$d({}, state, { walletUnlockPending: false, walletUnlockSucceded: true, walletUnlockResult: action.result }), - [WALLET_UNLOCK_FAILED]: (state, action) => _extends$e({}, state, { + [WALLET_UNLOCK_FAILED]: (state, action) => _extends$d({}, state, { walletUnlockPending: false, walletUnlockSucceded: false, walletUnlockResult: action.result }), - [WALLET_LOCK_START]: state => _extends$e({}, state, { + [WALLET_LOCK_START]: state => _extends$d({}, state, { walletLockPending: false, walletLockSucceded: null, walletLockResult: null }), - [WALLET_LOCK_COMPLETED]: (state, action) => _extends$e({}, state, { + [WALLET_LOCK_COMPLETED]: (state, action) => _extends$d({}, state, { walletLockPending: false, walletLockSucceded: true, walletLockResult: action.result }), - [WALLET_LOCK_FAILED]: (state, action) => _extends$e({}, state, { + [WALLET_LOCK_FAILED]: (state, action) => _extends$d({}, state, { walletLockPending: false, walletLockSucceded: false, walletLockResult: action.result }), - [SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$e({}, state, { + [SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$d({}, state, { transactionListFilter: action.data }), - [UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$e({}, state, { + [UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$d({}, state, { latestBlock: action.data }) }, defaultState$a); @@ -4679,14 +4663,14 @@ const makeSelectContentPositionForUri = uri => reselect.createSelector(selectSta return state.positions[id] ? state.positions[id][outpoint] : null; }); -var _extends$f = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +var _extends$e = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; const selectState$7 = state => state.notifications || {}; const selectToast = reselect.createSelector(selectState$7, state => { if (state.toasts.length) { const { id, params } = state.toasts[0]; - return _extends$f({ + return _extends$e({ id }, params); } diff --git a/src/constants/action_types.js b/src/constants/action_types.js index 4b07603..be13241 100644 --- a/src/constants/action_types.js +++ b/src/constants/action_types.js @@ -111,6 +111,7 @@ export const FILE_LIST_STARTED = 'FILE_LIST_STARTED'; export const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED'; export const FETCH_FILE_INFO_STARTED = 'FETCH_FILE_INFO_STARTED'; export const FETCH_FILE_INFO_COMPLETED = 'FETCH_FILE_INFO_COMPLETED'; +export const FETCH_FILE_INFO_FAILED = 'FETCH_FILE_INFO_FAILED'; export const LOADING_VIDEO_STARTED = 'LOADING_VIDEO_STARTED'; export const LOADING_VIDEO_COMPLETED = 'LOADING_VIDEO_COMPLETED'; export const LOADING_VIDEO_FAILED = 'LOADING_VIDEO_FAILED'; diff --git a/src/redux/actions/file.js b/src/redux/actions/file.js index 1697687..79d9b99 100644 --- a/src/redux/actions/file.js +++ b/src/redux/actions/file.js @@ -5,16 +5,21 @@ import { doToast } from 'redux/actions/notifications'; import { selectBalance } from 'redux/selectors/wallet'; import { makeSelectFileInfoForUri, selectDownloadingByOutpoint } from 'redux/selectors/file_info'; import { makeSelectStreamingUrlForUri } from 'redux/selectors/file'; +import { makeSelectClaimForUri } from 'redux/selectors/claims'; type Dispatch = (action: any) => any; type GetState = () => { file: FileState }; export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: GetResponse => any) { - return (dispatch: Dispatch) => { + return (dispatch: Dispatch, getState: () => any) => { + const state = getState(); + const { nout, txid } = makeSelectClaimForUri(uri)(state); + const outpoint = `${txid}:${nout}`; + dispatch({ - type: ACTIONS.PURCHASE_URI_STARTED, + type: ACTIONS.FETCH_FILE_INFO_STARTED, data: { - uri, + outpoint, }, }); @@ -26,8 +31,8 @@ export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: Get if (timeout) { dispatch({ - type: ACTIONS.PURCHASE_URI_FAILED, - data: { uri }, + type: ACTIONS.FETCH_FILE_INFO_FAILED, + data: { outpoint }, }); dispatch(doToast({ message: `File timeout for uri ${uri}`, isError: true })); @@ -56,6 +61,11 @@ export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: Get data: { uri }, }); + dispatch({ + type: ACTIONS.FETCH_FILE_INFO_FAILED, + data: { outpoint }, + }); + dispatch( doToast({ message: `Failed to view ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`, diff --git a/src/redux/reducers/file_info.js b/src/redux/reducers/file_info.js index 5f20148..cb86718 100644 --- a/src/redux/reducers/file_info.js +++ b/src/redux/reducers/file_info.js @@ -57,20 +57,27 @@ reducers[ACTIONS.FETCH_FILE_INFO_COMPLETED] = (state, action) => { }); }; +reducers[ACTIONS.FETCH_FILE_INFO_FAILED] = (state, action) => { + const { outpoint } = action.data; + const newFetching = Object.assign({}, state.fetching); + delete newFetching[outpoint]; + + return Object.assign({}, state, { + fetching: newFetching, + }); +}; + reducers[ACTIONS.DOWNLOADING_STARTED] = (state, action) => { const { uri, outpoint, fileInfo } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); const newDownloading = Object.assign({}, state.downloadingByOutpoint); - const newLoading = Object.assign({}, state.urisLoading); newDownloading[outpoint] = true; newByOutpoint[outpoint] = fileInfo; - delete newLoading[uri]; return Object.assign({}, state, { downloadingByOutpoint: newDownloading, - urisLoading: newLoading, byOutpoint: newByOutpoint, }); }; @@ -95,11 +102,9 @@ reducers[ACTIONS.DOWNLOADING_CANCELED] = (state, action) => { const newDownloading = Object.assign({}, state.downloadingByOutpoint); delete newDownloading[outpoint]; - delete newLoading[uri]; return Object.assign({}, state, { downloadingByOutpoint: newDownloading, - urisLoading: newLoading, }); }; @@ -133,36 +138,6 @@ reducers[ACTIONS.FILE_DELETE] = (state, action) => { }); }; -reducers[ACTIONS.LOADING_VIDEO_STARTED] = (state, action) => { - const { uri } = action.data; - - const newLoading = Object.assign({}, state.urisLoading); - newLoading[uri] = true; - - const newErrors = { ...state.errors }; - if (uri in newErrors) delete newErrors[uri]; - - return Object.assign({}, state, { - urisLoading: newLoading, - errors: { ...newErrors }, - }); -}; - -reducers[ACTIONS.LOADING_VIDEO_FAILED] = (state, action) => { - const { uri } = action.data; - - const newLoading = Object.assign({}, state.urisLoading); - delete newLoading[uri]; - - const newErrors = { ...state.errors }; - newErrors[uri] = true; - - return Object.assign({}, state, { - urisLoading: newLoading, - errors: { ...newErrors }, - }); -}; - reducers[ACTIONS.SET_FILE_LIST_SORT] = (state, action) => { const pageSortStates = { [PAGES.PUBLISHED]: 'fileListPublishedSort', -- 2.45.3