From d45c160b10f9e6f9e56fe724105e7381fdb5375f Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Tue, 7 Jan 2020 00:21:13 -0500 Subject: [PATCH 01/34] Adds proper comment type --- flow-typed/Comment.js | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/flow-typed/Comment.js b/flow-typed/Comment.js index f2f35b7..4619430 100644 --- a/flow-typed/Comment.js +++ b/flow-typed/Comment.js @@ -1,19 +1,22 @@ declare type Comment = { - author?: string, - author_url?: string, - claim_index?: number, - comment_id?: number, - downvotes?: number, - message: string, - omitted?: number, - reply_count?: number, - time_posted?: number, - upvotes?: number, - parent_id?: number, + comment: string, // comment body + comment_id: string, // sha256 digest + timestamp: number, // integer representing unix-time + is_hidden: boolean, // claim owner may enable/disable this + channel_id?: string, // claimId of channel signing this comment + channel_name?: string, // name of channel claim + channel_url?: string, // full lbry url to signing channel + signature?: string, // signature of comment by originating channel + signing_ts?: string, // timestamp used when signing this comment + is_channel_signature_valid?: boolean, // whether or not the signature could be validated + parent_id?: number, // comment_id of comment this is in reply to + claim_id?: string, // id linking to the claim this comment }; +// todo: relate individual comments to their commentId declare type CommentsState = { - byId: {}, - isLoading: boolean, commentsByUri: { [string]: string }, -} + byId: { [string]: Array }, + isLoading: boolean, + myComments: ?Set, +}; From 7c55a9e0f51b4efa2b01983b86d265e6282d2546 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Tue, 7 Jan 2020 00:22:57 -0500 Subject: [PATCH 02/34] Adds edit, hide, and abandon action types from new lbry sdk api --- dist/bundle.es.js | 9 +++++++++ src/constants/action_types.js | 9 +++++++++ src/redux/reducers/comments.js | 37 ++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 035f91c..da208a5 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -377,6 +377,15 @@ var action_types = /*#__PURE__*/Object.freeze({ COMMENT_CREATE_STARTED: COMMENT_CREATE_STARTED, COMMENT_CREATE_COMPLETED: COMMENT_CREATE_COMPLETED, COMMENT_CREATE_FAILED: COMMENT_CREATE_FAILED, + COMMENT_ABANDON_STARTED: COMMENT_ABANDON_STARTED, + COMMENT_ABANDON_COMPLETED: COMMENT_ABANDON_COMPLETED, + COMMENT_ABANDON_FAILED: COMMENT_ABANDON_FAILED, + COMMENT_HIDE_STARTED: COMMENT_HIDE_STARTED, + COMMENT_HIDE_COMPLETED: COMMENT_HIDE_COMPLETED, + COMMENT_HIDE_FAILED: COMMENT_HIDE_FAILED, + COMMENT_EDIT_STARTED: COMMENT_EDIT_STARTED, + COMMENT_EDIT_COMPLETED: COMMENT_EDIT_COMPLETED, + COMMENT_EDIT_FAILED: COMMENT_EDIT_FAILED, FILE_LIST_STARTED: FILE_LIST_STARTED, FILE_LIST_SUCCEEDED: FILE_LIST_SUCCEEDED, FETCH_FILE_INFO_STARTED: FETCH_FILE_INFO_STARTED, diff --git a/src/constants/action_types.js b/src/constants/action_types.js index ac23374..097b2cd 100644 --- a/src/constants/action_types.js +++ b/src/constants/action_types.js @@ -111,6 +111,15 @@ export const COMMENT_LIST_FAILED = 'COMMENT_LIST_FAILED'; export const COMMENT_CREATE_STARTED = 'COMMENT_CREATE_STARTED'; export const COMMENT_CREATE_COMPLETED = 'COMMENT_CREATE_COMPLETED'; export const COMMENT_CREATE_FAILED = 'COMMENT_CREATE_FAILED'; +export const COMMENT_ABANDON_STARTED = 'COMMENT_ABANDON_STARTED'; +export const COMMENT_ABANDON_COMPLETED = 'COMMENT_ABANDON_COMPLETED'; +export const COMMENT_ABANDON_FAILED = 'COMMENT_ABANDON_FAILED'; +export const COMMENT_EDIT_STARTED = 'COMMENT_EDIT_STARTED'; +export const COMMENT_EDIT_COMPLETED = 'COMMENT_EDIT_COMPLETED'; +export const COMMENT_EDIT_FAILED = 'COMMENT_EDIT_FAILED'; +export const COMMENT_HIDE_STARTED = 'COMMENT_HIDE_STARTED'; +export const COMMENT_HIDE_COMPLETED = 'COMMENT_HIDE_COMPLETED'; +export const COMMENT_HIDE_FAILED = 'COMMENT_HIDE_FAILED'; // Files export const FILE_LIST_STARTED = 'FILE_LIST_STARTED'; diff --git a/src/redux/reducers/comments.js b/src/redux/reducers/comments.js index 3d1738b..c3b9bd4 100644 --- a/src/redux/reducers/comments.js +++ b/src/redux/reducers/comments.js @@ -6,6 +6,7 @@ const defaultState: CommentsState = { byId: {}, commentsByUri: {}, isLoading: false, + myComments: undefined, }; export const commentReducer = handleActions( @@ -58,6 +59,42 @@ export const commentReducer = handleActions( ...state, isLoading: false, }), + [ACTIONS.COMMENT_ABANDON_STARTED]: (state: CommentsState, action: any) => ({ + ...state, + isLoading: true, + }), + [ACTIONS.COMMENT_ABANDON_COMPLETED]: (state: CommentsState, action: any) => ({ + ...state, + isLoading: false, + }), + [ACTIONS.COMMENT_ABANDON_FAILED]: (state: CommentsState, action: any) => ({ + ...state, + isLoading: false, + }), + [ACTIONS.COMMENT_EDIT_STARTED]: (state: CommentsState, action: any) => ({ + ...state, + isLoading: true, + }), + [ACTIONS.COMMENT_EDIT_COMPLETED]: (state: CommentsState, action: any) => ({ + ...state, + isLoading: false, + }), + [ACTIONS.COMMENT_EDIT_FAILED]: (state: CommentsState, action: any) => ({ + ...state, + isLoading: false, + }), + [ACTIONS.COMMENT_HIDE_STARTED]: (state: CommentsState, action: any) => ({ + ...state, + isLoading: true, + }), + [ACTIONS.COMMENT_HIDE_COMPLETED]: (state: CommentsState, action: any) => ({ + ...state, + isLoading: false, + }), + [ACTIONS.COMMENT_HIDE_FAILED]: (state: CommentsState, action: any) => ({ + ...state, + isLoading: false, + }), }, defaultState ); From 78ec8c3c16cd350068151233c3780d980bba54a7 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Thu, 9 Jan 2020 17:09:37 -0500 Subject: [PATCH 03/34] Adds edit, hide, and abandon action types from new lbry sdk api --- flow-typed/Lbry.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/flow-typed/Lbry.js b/flow-typed/Lbry.js index cc8a4ac..92ce9dd 100644 --- a/flow-typed/Lbry.js +++ b/flow-typed/Lbry.js @@ -125,6 +125,8 @@ declare type ChannelUpdateResponse = GenericTxResponse & { }; declare type CommentCreateResponse = Comment; +declare type CommentEditResponse = Comment; + declare type CommentListResponse = { items: Array, page: number, @@ -133,6 +135,16 @@ declare type CommentListResponse = { total_pages: number, }; +declare type CommentHideResponse = { + // keyed by the CommentIds entered + [string]: { hidden: boolean }, +}; + +declare type CommentAbandonResponse = { + // keyed by the CommentId given + [string]: { abandoned: boolean }, +}; + declare type ChannelListResponse = { items: Array, page: number, From ba9e68b1da73b067c38fa7693e569aeba45f9c1a Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Thu, 9 Jan 2020 17:10:54 -0500 Subject: [PATCH 04/34] claim_id is now guaranteed --- flow-typed/Comment.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flow-typed/Comment.js b/flow-typed/Comment.js index 4619430..368164c 100644 --- a/flow-typed/Comment.js +++ b/flow-typed/Comment.js @@ -1,6 +1,7 @@ declare type Comment = { comment: string, // comment body comment_id: string, // sha256 digest + claim_id: string, // id linking to the claim this comment timestamp: number, // integer representing unix-time is_hidden: boolean, // claim owner may enable/disable this channel_id?: string, // claimId of channel signing this comment @@ -10,7 +11,6 @@ declare type Comment = { signing_ts?: string, // timestamp used when signing this comment is_channel_signature_valid?: boolean, // whether or not the signature could be validated parent_id?: number, // comment_id of comment this is in reply to - claim_id?: string, // id linking to the claim this comment }; // todo: relate individual comments to their commentId From 586b07a2431c75f4fb30c370f270fad8a5c79ac5 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Thu, 9 Jan 2020 17:11:37 -0500 Subject: [PATCH 05/34] adds edit, hide, and abandon methods to call the API with --- src/lbry.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lbry.js b/src/lbry.js index ceb96f3..9fdd033 100644 --- a/src/lbry.js +++ b/src/lbry.js @@ -119,6 +119,11 @@ const Lbry: LbryTypes = { // Comments comment_list: (params = {}) => daemonCallWithResult('comment_list', params), comment_create: (params = {}) => daemonCallWithResult('comment_create', params), + // todo: implement these in reducers + comment_hide: (params = {}) => daemonCallWithResult('comment_hide', params), + comment_abandon: (params = {}) => daemonCallWithResult('comment_abandon', params), + comment_edit: (params = {}) => daemonCallWithResult('comment_hide', params), + // Connect to the sdk connect: () => { if (Lbry.connectPromise === null) { From 28440873346a21d4a5daf2524ff70104844b3c8c Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Thu, 9 Jan 2020 21:27:23 -0500 Subject: [PATCH 06/34] Schema change for `CommentsState` --- flow-typed/Comment.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/flow-typed/Comment.js b/flow-typed/Comment.js index 368164c..64ea974 100644 --- a/flow-typed/Comment.js +++ b/flow-typed/Comment.js @@ -16,7 +16,8 @@ declare type Comment = { // todo: relate individual comments to their commentId declare type CommentsState = { commentsByUri: { [string]: string }, - byId: { [string]: Array }, + byId: { [string]: Array }, + commentById: { [string]: Comment }, isLoading: boolean, - myComments: ?Set, + myComments: ?Set, }; From c171a38067ec9d3e806df9afb4d08e51065d307d Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Thu, 9 Jan 2020 21:27:59 -0500 Subject: [PATCH 07/34] Adds parent_id param to `comment_create` to allow replies --- src/redux/actions/comments.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/redux/actions/comments.js b/src/redux/actions/comments.js index dbf1d94..64b5344 100644 --- a/src/redux/actions/comments.js +++ b/src/redux/actions/comments.js @@ -55,9 +55,10 @@ export function doCommentCreate( myChannels && myChannels.find(myChannel => myChannel.name === channel); const channel_id = namedChannelClaim ? namedChannelClaim.claim_id : null; return Lbry.comment_create({ - comment, - claim_id, - channel_id, + comment: comment, + claim_id: claim_id, + channel_id: channel_id, + parent_id: parent_id, }) .then((result: Comment) => { dispatch({ From b65149fe003e301505b8c6a9bc9b95428dad62a7 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Thu, 9 Jan 2020 21:28:35 -0500 Subject: [PATCH 08/34] Refactors old reducers to be compliant with new schema --- src/redux/reducers/comments.js | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/redux/reducers/comments.js b/src/redux/reducers/comments.js index c3b9bd4..0513625 100644 --- a/src/redux/reducers/comments.js +++ b/src/redux/reducers/comments.js @@ -3,8 +3,9 @@ import * as ACTIONS from 'constants/action_types'; import { handleActions } from 'util/redux-utils'; const defaultState: CommentsState = { - byId: {}, - commentsByUri: {}, + commentById: {}, // commentId -> Comment + byId: {}, // ClaimID -> list of comments + commentsByUri: {}, // URI -> claimId isLoading: false, myComments: undefined, }; @@ -23,16 +24,23 @@ export const commentReducer = handleActions( [ACTIONS.COMMENT_CREATE_COMPLETED]: (state: CommentsState, action: any): CommentsState => { const { comment, claimId }: any = action.data; + const commentById = Object.assign({}, state.commentById); const byId = Object.assign({}, state.byId); const comments = byId[claimId]; - const newComments = comments.slice(); + const newCommentIds = comments.slice(); - newComments.unshift(comment); - byId[claimId] = newComments; + // add the comment by its ID + commentById[comment.comment_id] = comment; + + // push the comment_id to the top of ID list + newCommentIds.unshift(comment.comment_id); + byId[claimId] = newCommentIds; return { ...state, + commentById, byId, + isLoading: false, }; }, @@ -40,16 +48,26 @@ export const commentReducer = handleActions( [ACTIONS.COMMENT_LIST_COMPLETED]: (state: CommentsState, action: any) => { const { comments, claimId, uri } = action.data; + + const commentById = Object.assign({}, state.commentById); const byId = Object.assign({}, state.byId); const commentsByUri = Object.assign({}, state.commentsByUri); if (comments) { - byId[claimId] = comments; + const commentIds = Array(comments.length); + // map the comment_ids to the new comments + for (let i = 0; i < comments.length; i++) { + commentIds[i] = comments[i].comment_id; + commentById[commentIds[i]] = comments[i]; + } + + byId[claimId] = commentIds; commentsByUri[uri] = claimId; } return { ...state, byId, + commentById, commentsByUri, isLoading: false, }; From 1038ff16c87d69b192b914773a5d07dbee8eb1e6 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Thu, 9 Jan 2020 21:29:16 -0500 Subject: [PATCH 09/34] Creates new selectors that are more consistent with the rest of the redux selectors for claims --- src/redux/selectors/comments.js | 37 +++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/redux/selectors/comments.js b/src/redux/selectors/comments.js index c391a5c..048e7f2 100644 --- a/src/redux/selectors/comments.js +++ b/src/redux/selectors/comments.js @@ -5,9 +5,37 @@ const selectState = state => state.comments || {}; export const selectCommentsById = createSelector( selectState, - state => state.byId || {} + state => state.commentById || {} ); +export const selectCommentsByClaimId = createSelector( + selectState, + selectCommentsById, + (state, byId) => { + const byClaimId = state.byId || {}; + const comments = {}; + + // for every claimId -> commentId, put comments in the object + Object.keys(byClaimId).forEach(claimId => { + // get all the commentIds that commented on this ClaimId + const commentIds = byClaimId[claimId]; + + // map a new array of comments by the claimId + comments[claimId] = Array(commentIds === null ? 0 : commentIds.length); + for (let i = 0; i < commentIds.length; i++) { + comments[claimId][i] = byId[commentIds[i]]; + } + }); + + return comments; + } +); + +// previously this used a mapping from claimId -> Array +/* export const selectCommentsById = createSelector( + selectState, + state => state.byId || {} +); */ export const selectCommentsByUri = createSelector( selectState, state => { @@ -21,16 +49,17 @@ export const selectCommentsByUri = createSelector( comments[uri] = claimId; } }); + return comments; } ); export const makeSelectCommentsForUri = (uri: string) => createSelector( - selectCommentsById, + selectCommentsByClaimId, selectCommentsByUri, - (byId, byUri) => { + (byClaimId, byUri) => { const claimId = byUri[uri]; - return byId && byId[claimId]; + return byClaimId && byClaimId[claimId]; } ); From ff9493f33494ddd9b69a7f95a04ac14919990dc8 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Thu, 9 Jan 2020 21:29:54 -0500 Subject: [PATCH 10/34] Reflect changes in dist code --- dist/bundle.es.js | 132 ++++++++++++++++++++++++++++++++----- dist/flow-typed/Comment.js | 32 +++++---- dist/flow-typed/Lbry.js | 12 ++++ 3 files changed, 145 insertions(+), 31 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index da208a5..e8b420a 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -134,6 +134,15 @@ const COMMENT_LIST_FAILED = 'COMMENT_LIST_FAILED'; const COMMENT_CREATE_STARTED = 'COMMENT_CREATE_STARTED'; const COMMENT_CREATE_COMPLETED = 'COMMENT_CREATE_COMPLETED'; const COMMENT_CREATE_FAILED = 'COMMENT_CREATE_FAILED'; +const COMMENT_ABANDON_STARTED = 'COMMENT_ABANDON_STARTED'; +const COMMENT_ABANDON_COMPLETED = 'COMMENT_ABANDON_COMPLETED'; +const COMMENT_ABANDON_FAILED = 'COMMENT_ABANDON_FAILED'; +const COMMENT_EDIT_STARTED = 'COMMENT_EDIT_STARTED'; +const COMMENT_EDIT_COMPLETED = 'COMMENT_EDIT_COMPLETED'; +const COMMENT_EDIT_FAILED = 'COMMENT_EDIT_FAILED'; +const COMMENT_HIDE_STARTED = 'COMMENT_HIDE_STARTED'; +const COMMENT_HIDE_COMPLETED = 'COMMENT_HIDE_COMPLETED'; +const COMMENT_HIDE_FAILED = 'COMMENT_HIDE_FAILED'; // Files const FILE_LIST_STARTED = 'FILE_LIST_STARTED'; @@ -380,12 +389,12 @@ var action_types = /*#__PURE__*/Object.freeze({ COMMENT_ABANDON_STARTED: COMMENT_ABANDON_STARTED, COMMENT_ABANDON_COMPLETED: COMMENT_ABANDON_COMPLETED, COMMENT_ABANDON_FAILED: COMMENT_ABANDON_FAILED, - COMMENT_HIDE_STARTED: COMMENT_HIDE_STARTED, - COMMENT_HIDE_COMPLETED: COMMENT_HIDE_COMPLETED, - COMMENT_HIDE_FAILED: COMMENT_HIDE_FAILED, COMMENT_EDIT_STARTED: COMMENT_EDIT_STARTED, COMMENT_EDIT_COMPLETED: COMMENT_EDIT_COMPLETED, COMMENT_EDIT_FAILED: COMMENT_EDIT_FAILED, + COMMENT_HIDE_STARTED: COMMENT_HIDE_STARTED, + COMMENT_HIDE_COMPLETED: COMMENT_HIDE_COMPLETED, + COMMENT_HIDE_FAILED: COMMENT_HIDE_FAILED, FILE_LIST_STARTED: FILE_LIST_STARTED, FILE_LIST_SUCCEEDED: FILE_LIST_SUCCEEDED, FETCH_FILE_INFO_STARTED: FETCH_FILE_INFO_STARTED, @@ -925,6 +934,11 @@ const Lbry = { // Comments comment_list: (params = {}) => daemonCallWithResult('comment_list', params), comment_create: (params = {}) => daemonCallWithResult('comment_create', params), + // todo: implement these in reducers + comment_hide: (params = {}) => daemonCallWithResult('comment_hide', params), + comment_abandon: (params = {}) => daemonCallWithResult('comment_abandon', params), + comment_edit: (params = {}) => daemonCallWithResult('comment_hide', params), + // Connect to the sdk connect: () => { if (Lbry.connectPromise === null) { @@ -1232,6 +1246,18 @@ function buildURI(UrlObj, includeProto = true, protoDefault = 'lbry://') { deprecatedParts = _objectWithoutProperties(UrlObj, ['streamName', 'streamClaimId', 'channelName', 'channelClaimId', 'primaryClaimSequence', 'primaryBidPosition', 'secondaryClaimSequence', 'secondaryBidPosition']); const { claimId, claimName, contentName } = deprecatedParts; + { + if (claimId) { + console.error(__("'claimId' should no longer be used. Use 'streamClaimId' or 'channelClaimId' instead")); + } + if (claimName) { + console.error(__("'claimName' should no longer be used. Use 'streamClaimName' or 'channelClaimName' instead")); + } + if (contentName) { + console.error(__("'contentName' should no longer be used. Use 'streamName' instead")); + } + } + if (!claimName && !channelName && !streamName) { console.error(__("'claimName', 'channelName', and 'streamName' are all empty. One must be present to build a url.")); } @@ -4104,9 +4130,10 @@ function doCommentCreate(comment = '', claim_id = '', channel, parent_id) { const namedChannelClaim = myChannels && myChannels.find(myChannel => myChannel.name === channel); const channel_id = namedChannelClaim ? namedChannelClaim.claim_id : null; return lbryProxy.comment_create({ - comment, - claim_id, - channel_id + comment: comment, + claim_id: claim_id, + channel_id: channel_id, + parent_id: parent_id }).then(result => { dispatch({ type: COMMENT_CREATE_COMPLETED, @@ -4542,9 +4569,11 @@ const handleActions = (actionMap, defaultState) => (state = defaultState, action var _extends$7 = 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$1 = { - byId: {}, - commentsByUri: {}, - isLoading: false + commentById: {}, // commentId -> Comment + byId: {}, // ClaimID -> list of comments + commentsByUri: {}, // URI -> claimId + isLoading: false, + myComments: undefined }; const commentReducer = handleActions({ @@ -4558,15 +4587,22 @@ const commentReducer = handleActions({ [COMMENT_CREATE_COMPLETED]: (state, action) => { const { comment, claimId } = action.data; + const commentById = Object.assign({}, state.commentById); const byId = Object.assign({}, state.byId); const comments = byId[claimId]; - const newComments = comments.slice(); + const newCommentIds = comments.slice(); - newComments.unshift(comment); - byId[claimId] = newComments; + // add the comment by its ID + commentById[comment.comment_id] = comment; + + // push the comment_id to the top of ID list + newCommentIds.unshift(comment.comment_id); + byId[claimId] = newCommentIds; return _extends$7({}, state, { - byId + commentById, + byId, + isLoading: false }); }, @@ -4574,15 +4610,25 @@ const commentReducer = handleActions({ [COMMENT_LIST_COMPLETED]: (state, action) => { const { comments, claimId, uri } = action.data; + + const commentById = Object.assign({}, state.commentById); const byId = Object.assign({}, state.byId); const commentsByUri = Object.assign({}, state.commentsByUri); if (comments) { - byId[claimId] = comments; + const commentIds = Array(comments.length); + // map the comment_ids to the new comments + for (let i = 0; i < comments.length; i++) { + commentIds[i] = comments[i].comment_id; + commentById[commentIds[i]] = comments[i]; + } + + byId[claimId] = commentIds; commentsByUri[uri] = claimId; } return _extends$7({}, state, { byId, + commentById, commentsByUri, isLoading: false }); @@ -4590,6 +4636,33 @@ const commentReducer = handleActions({ [COMMENT_LIST_FAILED]: (state, action) => _extends$7({}, state, { isLoading: false + }), + [COMMENT_ABANDON_STARTED]: (state, action) => _extends$7({}, state, { + isLoading: true + }), + [COMMENT_ABANDON_COMPLETED]: (state, action) => _extends$7({}, state, { + isLoading: false + }), + [COMMENT_ABANDON_FAILED]: (state, action) => _extends$7({}, state, { + isLoading: false + }), + [COMMENT_EDIT_STARTED]: (state, action) => _extends$7({}, state, { + isLoading: true + }), + [COMMENT_EDIT_COMPLETED]: (state, action) => _extends$7({}, state, { + isLoading: false + }), + [COMMENT_EDIT_FAILED]: (state, action) => _extends$7({}, state, { + isLoading: false + }), + [COMMENT_HIDE_STARTED]: (state, action) => _extends$7({}, state, { + isLoading: true + }), + [COMMENT_HIDE_COMPLETED]: (state, action) => _extends$7({}, state, { + isLoading: false + }), + [COMMENT_HIDE_FAILED]: (state, action) => _extends$7({}, state, { + isLoading: false }) }, defaultState$1); @@ -5470,8 +5543,32 @@ const selectError = reselect.createSelector(selectState$7, state => { const selectState$8 = state => state.comments || {}; -const selectCommentsById = reselect.createSelector(selectState$8, state => state.byId || {}); +const selectCommentsById = reselect.createSelector(selectState$8, state => state.commentById || {}); +const selectCommentsByClaimId = reselect.createSelector(selectState$8, selectCommentsById, (state, byId) => { + const byClaimId = state.byId || {}; + const comments = {}; + + // for every claimId -> commentId, put comments in the object + Object.keys(byClaimId).forEach(claimId => { + // get all the commentIds that commented on this ClaimId + const commentIds = byClaimId[claimId]; + + // map a new array of comments by the claimId + comments[claimId] = Array(commentIds === null ? 0 : commentIds.length); + for (let i = 0; i < commentIds.length; i++) { + comments[claimId][i] = byId[commentIds[i]]; + } + }); + + return comments; +}); + +// previously this used a mapping from claimId -> Array +/* export const selectCommentsById = createSelector( + selectState, + state => state.byId || {} +); */ const selectCommentsByUri = reselect.createSelector(selectState$8, state => { const byUri = state.commentsByUri || {}; const comments = {}; @@ -5483,12 +5580,13 @@ const selectCommentsByUri = reselect.createSelector(selectState$8, state => { comments[uri] = claimId; } }); + return comments; }); -const makeSelectCommentsForUri = uri => reselect.createSelector(selectCommentsById, selectCommentsByUri, (byId, byUri) => { +const makeSelectCommentsForUri = uri => reselect.createSelector(selectCommentsByClaimId, selectCommentsByUri, (byClaimId, byUri) => { const claimId = byUri[uri]; - return byId && byId[claimId]; + return byClaimId && byClaimId[claimId]; }); // diff --git a/dist/flow-typed/Comment.js b/dist/flow-typed/Comment.js index f2f35b7..64ea974 100644 --- a/dist/flow-typed/Comment.js +++ b/dist/flow-typed/Comment.js @@ -1,19 +1,23 @@ declare type Comment = { - author?: string, - author_url?: string, - claim_index?: number, - comment_id?: number, - downvotes?: number, - message: string, - omitted?: number, - reply_count?: number, - time_posted?: number, - upvotes?: number, - parent_id?: number, + comment: string, // comment body + comment_id: string, // sha256 digest + claim_id: string, // id linking to the claim this comment + timestamp: number, // integer representing unix-time + is_hidden: boolean, // claim owner may enable/disable this + channel_id?: string, // claimId of channel signing this comment + channel_name?: string, // name of channel claim + channel_url?: string, // full lbry url to signing channel + signature?: string, // signature of comment by originating channel + signing_ts?: string, // timestamp used when signing this comment + is_channel_signature_valid?: boolean, // whether or not the signature could be validated + parent_id?: number, // comment_id of comment this is in reply to }; +// todo: relate individual comments to their commentId declare type CommentsState = { - byId: {}, - isLoading: boolean, commentsByUri: { [string]: string }, -} + byId: { [string]: Array }, + commentById: { [string]: Comment }, + isLoading: boolean, + myComments: ?Set, +}; diff --git a/dist/flow-typed/Lbry.js b/dist/flow-typed/Lbry.js index cc8a4ac..92ce9dd 100644 --- a/dist/flow-typed/Lbry.js +++ b/dist/flow-typed/Lbry.js @@ -125,6 +125,8 @@ declare type ChannelUpdateResponse = GenericTxResponse & { }; declare type CommentCreateResponse = Comment; +declare type CommentEditResponse = Comment; + declare type CommentListResponse = { items: Array, page: number, @@ -133,6 +135,16 @@ declare type CommentListResponse = { total_pages: number, }; +declare type CommentHideResponse = { + // keyed by the CommentIds entered + [string]: { hidden: boolean }, +}; + +declare type CommentAbandonResponse = { + // keyed by the CommentId given + [string]: { abandoned: boolean }, +}; + declare type ChannelListResponse = { items: Array, page: number, From 24707eea5b8c5095edf0ba981c3220fedb5bcb41 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Mon, 13 Jan 2020 11:53:35 -0500 Subject: [PATCH 11/34] fix type on parent_id param --- src/redux/actions/comments.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/redux/actions/comments.js b/src/redux/actions/comments.js index 64b5344..a56b5a1 100644 --- a/src/redux/actions/comments.js +++ b/src/redux/actions/comments.js @@ -43,7 +43,7 @@ export function doCommentCreate( comment: string = '', claim_id: string = '', channel: ?string, - parent_id?: number + parent_id?: string, ) { return (dispatch: Dispatch, getState: GetState) => { const state = getState(); From 13cd56dabccfb359913786687a2d79f4cdf88fec Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Mon, 13 Jan 2020 16:52:23 -0500 Subject: [PATCH 12/34] "comment edit" -> "comment update" --- flow-typed/Lbry.js | 2 +- src/constants/action_types.js | 6 ++-- src/lbry.js | 4 +-- src/redux/reducers/comments.js | 65 +++++++++++++++++++++++++++------- 4 files changed, 59 insertions(+), 18 deletions(-) diff --git a/flow-typed/Lbry.js b/flow-typed/Lbry.js index 92ce9dd..8afe66f 100644 --- a/flow-typed/Lbry.js +++ b/flow-typed/Lbry.js @@ -125,7 +125,7 @@ declare type ChannelUpdateResponse = GenericTxResponse & { }; declare type CommentCreateResponse = Comment; -declare type CommentEditResponse = Comment; +declare type CommentUpdateResponse = Comment; declare type CommentListResponse = { items: Array, diff --git a/src/constants/action_types.js b/src/constants/action_types.js index 097b2cd..0c31338 100644 --- a/src/constants/action_types.js +++ b/src/constants/action_types.js @@ -114,9 +114,9 @@ export const COMMENT_CREATE_FAILED = 'COMMENT_CREATE_FAILED'; export const COMMENT_ABANDON_STARTED = 'COMMENT_ABANDON_STARTED'; export const COMMENT_ABANDON_COMPLETED = 'COMMENT_ABANDON_COMPLETED'; export const COMMENT_ABANDON_FAILED = 'COMMENT_ABANDON_FAILED'; -export const COMMENT_EDIT_STARTED = 'COMMENT_EDIT_STARTED'; -export const COMMENT_EDIT_COMPLETED = 'COMMENT_EDIT_COMPLETED'; -export const COMMENT_EDIT_FAILED = 'COMMENT_EDIT_FAILED'; +export const COMMENT_UPDATE_STARTED = 'COMMENT_UPDATE_STARTED'; +export const COMMENT_UPDATE_COMPLETED = 'COMMENT_UPDATE_COMPLETED'; +export const COMMENT_UPDATE_FAILED = 'COMMENT_UPDATE_FAILED'; export const COMMENT_HIDE_STARTED = 'COMMENT_HIDE_STARTED'; export const COMMENT_HIDE_COMPLETED = 'COMMENT_HIDE_COMPLETED'; export const COMMENT_HIDE_FAILED = 'COMMENT_HIDE_FAILED'; diff --git a/src/lbry.js b/src/lbry.js index 9fdd033..f6cc88c 100644 --- a/src/lbry.js +++ b/src/lbry.js @@ -119,10 +119,10 @@ const Lbry: LbryTypes = { // Comments comment_list: (params = {}) => daemonCallWithResult('comment_list', params), comment_create: (params = {}) => daemonCallWithResult('comment_create', params), - // todo: implement these in reducers comment_hide: (params = {}) => daemonCallWithResult('comment_hide', params), comment_abandon: (params = {}) => daemonCallWithResult('comment_abandon', params), - comment_edit: (params = {}) => daemonCallWithResult('comment_hide', params), + // requires SDK ver. 0.53.0 + comment_update: (params = {}) => daemonCallWithResult('comment_update', params), // Connect to the sdk connect: () => { diff --git a/src/redux/reducers/comments.js b/src/redux/reducers/comments.js index 0513625..8876b0e 100644 --- a/src/redux/reducers/comments.js +++ b/src/redux/reducers/comments.js @@ -23,7 +23,7 @@ export const commentReducer = handleActions( }), [ACTIONS.COMMENT_CREATE_COMPLETED]: (state: CommentsState, action: any): CommentsState => { - const { comment, claimId }: any = action.data; + const { comment, claimId }: { comment: Comment, claimId: string } = action.data; const commentById = Object.assign({}, state.commentById); const byId = Object.assign({}, state.byId); const comments = byId[claimId]; @@ -54,7 +54,11 @@ export const commentReducer = handleActions( const commentsByUri = Object.assign({}, state.commentsByUri); if (comments) { + // we use an Array to preserve order of listing + // in reality this doesn't matter and we can just + // sort comments by their timestamp const commentIds = Array(comments.length); + // map the comment_ids to the new comments for (let i = 0; i < comments.length; i++) { commentIds[i] = comments[i].comment_id; @@ -81,34 +85,71 @@ export const commentReducer = handleActions( ...state, isLoading: true, }), - [ACTIONS.COMMENT_ABANDON_COMPLETED]: (state: CommentsState, action: any) => ({ - ...state, - isLoading: false, - }), + // remove the existing comment from the id -> comment list and claim -> commentIds + [ACTIONS.COMMENT_ABANDON_COMPLETED]: (state: CommentsState, action: any) => { + const { comment_id, abandoned } = action.data; + const commentById = Object.assign({}, state.commentById); + const byId = Object.assign({}, state.byId); + + if (abandoned && comment_id in abandoned) { + // messy but necessary for the time being + const comment: Comment = commentById[comment_id]; + const commentIds = byId[comment.claim_id]; + byId[comment.claim_id] = commentIds.filter(commentId => commentId !== comment_id); + + Object.keys(commentById).forEach(commentId => { + if (commentId === comment_id) { + delete commentById[commentId]; + } + }); + } + return { + ...state, + commentById, + byId, + isLoading: false, + }; + }, + // do nothing [ACTIONS.COMMENT_ABANDON_FAILED]: (state: CommentsState, action: any) => ({ ...state, isLoading: false, }), - [ACTIONS.COMMENT_EDIT_STARTED]: (state: CommentsState, action: any) => ({ + // do nothing + [ACTIONS.COMMENT_UPDATE_STARTED]: (state: CommentsState, action: any) => ({ ...state, isLoading: true, }), - [ACTIONS.COMMENT_EDIT_COMPLETED]: (state: CommentsState, action: any) => ({ - ...state, - isLoading: false, - }), - [ACTIONS.COMMENT_EDIT_FAILED]: (state: CommentsState, action: any) => ({ + // replace existing comment with comment returned here under its comment_id + [ACTIONS.COMMENT_UPDATE_COMPLETED]: (state: CommentsState, action: any) => { + const { comment } = action.data; + const commentById = Object.assign({}, state.commentById); + + if (comment) { + commentById[comment.comment_id] = comment; + } + + return { + ...state, + commentById, + isLoading: false, + }; + }, + // nothing can be done here + [ACTIONS.COMMENT_UPDATE_FAILED]: (state: CommentsState, action: any) => ({ ...state, isLoading: false, }), + // nothing can really be done here [ACTIONS.COMMENT_HIDE_STARTED]: (state: CommentsState, action: any) => ({ ...state, isLoading: true, }), [ACTIONS.COMMENT_HIDE_COMPLETED]: (state: CommentsState, action: any) => ({ - ...state, + ...state, // todo: add HiddenComments state & create selectors isLoading: false, }), + // nothing can be done here [ACTIONS.COMMENT_HIDE_FAILED]: (state: CommentsState, action: any) => ({ ...state, isLoading: false, From c0db949a53dee4b06acfcc96d7f2a874d3f6e468 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Mon, 13 Jan 2020 16:55:28 -0500 Subject: [PATCH 13/34] lint --- src/constants/shared_preferences.js | 12 ++++---- src/redux/actions/content.js | 3 +- src/redux/actions/sync.js | 7 +++-- src/redux/reducers/blocked.js | 3 +- src/redux/reducers/claims.js | 3 +- src/redux/selectors/content.js | 19 +++++++----- src/redux/selectors/notifications.js | 44 ++++++++++++++++------------ 7 files changed, 53 insertions(+), 38 deletions(-) diff --git a/src/constants/shared_preferences.js b/src/constants/shared_preferences.js index 56faf8f..e508e83 100644 --- a/src/constants/shared_preferences.js +++ b/src/constants/shared_preferences.js @@ -1,10 +1,10 @@ /* -* How to use this file: -* Settings exported from here will trigger the setting to be -* sent to the preference middleware when set using the -* usual setDaemonSettings and clearDaemonSettings methods. -* -* See redux/settings/actions in the app for where this is used. + * How to use this file: + * Settings exported from here will trigger the setting to be + * sent to the preference middleware when set using the + * usual setDaemonSettings and clearDaemonSettings methods. + * + * See redux/settings/actions in the app for where this is used. */ import * as DAEMON_SETTINGS from './daemon_settings'; diff --git a/src/redux/actions/content.js b/src/redux/actions/content.js index fff0f11..2654f74 100644 --- a/src/redux/actions/content.js +++ b/src/redux/actions/content.js @@ -1,7 +1,8 @@ +// @flow import * as ACTIONS from 'constants/action_types'; export function savePosition(claimId: string, outpoint: string, position: number) { - return dispatch => { + return (dispatch: Dispatch) => { dispatch({ type: ACTIONS.SET_CONTENT_POSITION, data: { claimId, outpoint, position }, diff --git a/src/redux/actions/sync.js b/src/redux/actions/sync.js index 41a25ea..7f80d33 100644 --- a/src/redux/actions/sync.js +++ b/src/redux/actions/sync.js @@ -14,7 +14,7 @@ type SharedData = { function extractUserState(rawObj: SharedData) { if (rawObj && rawObj.version === '0.1' && rawObj.value) { - const { subscriptions, tags, blocked, settings} = rawObj.value; + const { subscriptions, tags, blocked, settings } = rawObj.value; return { ...(subscriptions ? { subscriptions } : {}), @@ -30,7 +30,10 @@ function extractUserState(rawObj: SharedData) { export function doPopulateSharedUserState(sharedSettings: any) { return (dispatch: Dispatch) => { const { subscriptions, tags, blocked, settings } = extractUserState(sharedSettings); - dispatch({ type: ACTIONS.USER_STATE_POPULATE, data: { subscriptions, tags, blocked, settings } }); + dispatch({ + type: ACTIONS.USER_STATE_POPULATE, + data: { subscriptions, tags, blocked, settings }, + }); }; } diff --git a/src/redux/reducers/blocked.js b/src/redux/reducers/blocked.js index b69d9c9..c688936 100644 --- a/src/redux/reducers/blocked.js +++ b/src/redux/reducers/blocked.js @@ -33,8 +33,7 @@ export const blockedReducer = handleActions( const { blocked } = action.data; return { ...state, - blockedChannels: - blocked && blocked.length ? blocked : state.blockedChannels, + blockedChannels: blocked && blocked.length ? blocked : state.blockedChannels, }; }, }, diff --git a/src/redux/reducers/claims.js b/src/redux/reducers/claims.js index 8e6b121..56a4383 100644 --- a/src/redux/reducers/claims.js +++ b/src/redux/reducers/claims.js @@ -265,7 +265,8 @@ reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED] = (state: State, action: any): const paginatedClaimsByChannel = Object.assign({}, state.paginatedClaimsByChannel); // check if count has changed - that means cached pagination will be wrong, so clear it const previousCount = paginatedClaimsByChannel[uri] && paginatedClaimsByChannel[uri]['itemCount']; - const byChannel = (claimsInChannel === previousCount) ? Object.assign({}, paginatedClaimsByChannel[uri]) : {}; + const byChannel = + claimsInChannel === previousCount ? Object.assign({}, paginatedClaimsByChannel[uri]) : {}; const allClaimIds = new Set(byChannel.all); const currentPageClaimIds = []; const byId = Object.assign({}, state.byId); diff --git a/src/redux/selectors/content.js b/src/redux/selectors/content.js index f494fab..2daac6e 100644 --- a/src/redux/selectors/content.js +++ b/src/redux/selectors/content.js @@ -1,14 +1,19 @@ +// @flow import { createSelector } from 'reselect'; import { makeSelectClaimForUri } from 'redux/selectors/claims'; export const selectState = (state: any) => state.content || {}; export const makeSelectContentPositionForUri = (uri: string) => - createSelector(selectState, makeSelectClaimForUri(uri), (state, claim) => { - if (!claim) { - return null; + createSelector( + selectState, + makeSelectClaimForUri(uri), + (state, claim) => { + if (!claim) { + return null; + } + const outpoint = `${claim.txid}:${claim.nout}`; + const id = claim.claim_id; + return state.positions[id] ? state.positions[id][outpoint] : null; } - const outpoint = `${claim.txid}:${claim.nout}`; - const id = claim.claim_id; - return state.positions[id] ? state.positions[id][outpoint] : null; - }); + ); diff --git a/src/redux/selectors/notifications.js b/src/redux/selectors/notifications.js index 00844be..8894442 100644 --- a/src/redux/selectors/notifications.js +++ b/src/redux/selectors/notifications.js @@ -1,26 +1,32 @@ import { createSelector } from 'reselect'; -export const selectState = (state) => state.notifications || {}; +export const selectState = state => state.notifications || {}; -export const selectToast = createSelector(selectState, (state) => { - if (state.toasts.length) { - const { id, params } = state.toasts[0]; - return { - id, - ...params, - }; +export const selectToast = createSelector( + selectState, + state => { + if (state.toasts.length) { + const { id, params } = state.toasts[0]; + return { + id, + ...params, + }; + } + + return null; } +); - return null; -}); +export const selectError = createSelector( + selectState, + state => { + if (state.errors.length) { + const { error } = state.errors[0]; + return { + error, + }; + } -export const selectError = createSelector(selectState, (state) => { - if (state.errors.length) { - const { error } = state.errors[0]; - return { - error, - }; + return null; } - - return null; -}); +); From 2bdbf3d645baabaf59fdaf08c7cf735118cead24 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Mon, 13 Jan 2020 17:00:04 -0500 Subject: [PATCH 14/34] Implements reducers for COMMENT_UPDATE, COMMENT_HIDE, and COMMENT_ABANDON --- dist/bundle.es.js | 194 +++++++++++++++++++++++++++------- dist/flow-typed/Lbry.js | 6 +- flow-typed/Lbry.js | 4 + src/index.js | 8 +- src/redux/actions/comments.js | 99 ++++++++++++++++- 5 files changed, 271 insertions(+), 40 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index e8b420a..9e3c5e6 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -137,9 +137,9 @@ const COMMENT_CREATE_FAILED = 'COMMENT_CREATE_FAILED'; const COMMENT_ABANDON_STARTED = 'COMMENT_ABANDON_STARTED'; const COMMENT_ABANDON_COMPLETED = 'COMMENT_ABANDON_COMPLETED'; const COMMENT_ABANDON_FAILED = 'COMMENT_ABANDON_FAILED'; -const COMMENT_EDIT_STARTED = 'COMMENT_EDIT_STARTED'; -const COMMENT_EDIT_COMPLETED = 'COMMENT_EDIT_COMPLETED'; -const COMMENT_EDIT_FAILED = 'COMMENT_EDIT_FAILED'; +const COMMENT_UPDATE_STARTED = 'COMMENT_UPDATE_STARTED'; +const COMMENT_UPDATE_COMPLETED = 'COMMENT_UPDATE_COMPLETED'; +const COMMENT_UPDATE_FAILED = 'COMMENT_UPDATE_FAILED'; const COMMENT_HIDE_STARTED = 'COMMENT_HIDE_STARTED'; const COMMENT_HIDE_COMPLETED = 'COMMENT_HIDE_COMPLETED'; const COMMENT_HIDE_FAILED = 'COMMENT_HIDE_FAILED'; @@ -389,9 +389,9 @@ var action_types = /*#__PURE__*/Object.freeze({ COMMENT_ABANDON_STARTED: COMMENT_ABANDON_STARTED, COMMENT_ABANDON_COMPLETED: COMMENT_ABANDON_COMPLETED, COMMENT_ABANDON_FAILED: COMMENT_ABANDON_FAILED, - COMMENT_EDIT_STARTED: COMMENT_EDIT_STARTED, - COMMENT_EDIT_COMPLETED: COMMENT_EDIT_COMPLETED, - COMMENT_EDIT_FAILED: COMMENT_EDIT_FAILED, + COMMENT_UPDATE_STARTED: COMMENT_UPDATE_STARTED, + COMMENT_UPDATE_COMPLETED: COMMENT_UPDATE_COMPLETED, + COMMENT_UPDATE_FAILED: COMMENT_UPDATE_FAILED, COMMENT_HIDE_STARTED: COMMENT_HIDE_STARTED, COMMENT_HIDE_COMPLETED: COMMENT_HIDE_COMPLETED, COMMENT_HIDE_FAILED: COMMENT_HIDE_FAILED, @@ -783,12 +783,12 @@ var daemon_settings = /*#__PURE__*/Object.freeze({ }); /* -* How to use this file: -* Settings exported from here will trigger the setting to be -* sent to the preference middleware when set using the -* usual setDaemonSettings and clearDaemonSettings methods. -* -* See redux/settings/actions in the app for where this is used. + * How to use this file: + * Settings exported from here will trigger the setting to be + * sent to the preference middleware when set using the + * usual setDaemonSettings and clearDaemonSettings methods. + * + * See redux/settings/actions in the app for where this is used. */ const WALLET_SERVERS = LBRYUM_SERVERS; @@ -934,10 +934,10 @@ const Lbry = { // Comments comment_list: (params = {}) => daemonCallWithResult('comment_list', params), comment_create: (params = {}) => daemonCallWithResult('comment_create', params), - // todo: implement these in reducers comment_hide: (params = {}) => daemonCallWithResult('comment_hide', params), comment_abandon: (params = {}) => daemonCallWithResult('comment_abandon', params), - comment_edit: (params = {}) => daemonCallWithResult('comment_hide', params), + // requires SDK ver. 0.53.0 + comment_update: (params = {}) => daemonCallWithResult('comment_update', params), // Connect to the sdk connect: () => { @@ -1246,18 +1246,6 @@ function buildURI(UrlObj, includeProto = true, protoDefault = 'lbry://') { deprecatedParts = _objectWithoutProperties(UrlObj, ['streamName', 'streamClaimId', 'channelName', 'channelClaimId', 'primaryClaimSequence', 'primaryBidPosition', 'secondaryClaimSequence', 'secondaryBidPosition']); const { claimId, claimName, contentName } = deprecatedParts; - { - if (claimId) { - console.error(__("'claimId' should no longer be used. Use 'streamClaimId' or 'channelClaimId' instead")); - } - if (claimName) { - console.error(__("'claimName' should no longer be used. Use 'streamClaimName' or 'channelClaimName' instead")); - } - if (contentName) { - console.error(__("'contentName' should no longer be used. Use 'streamName' instead")); - } - } - if (!claimName && !channelName && !streamName) { console.error(__("'claimName', 'channelName', and 'streamName' are all empty. One must be present to build a url.")); } @@ -1570,7 +1558,10 @@ function extractUserState(rawObj) { function doPopulateSharedUserState(sharedSettings) { return dispatch => { const { subscriptions, tags, blocked, settings } = extractUserState(sharedSettings); - dispatch({ type: USER_STATE_POPULATE, data: { subscriptions, tags, blocked, settings } }); + dispatch({ + type: USER_STATE_POPULATE, + data: { subscriptions, tags, blocked, settings } + }); }; } @@ -4053,6 +4044,8 @@ const doUpdateSearchOptions = newOptions => (dispatch, getState) => { } }; +// + function savePosition(claimId, outpoint, position) { return dispatch => { dispatch({ @@ -4155,6 +4148,89 @@ function doCommentCreate(comment = '', claim_id = '', channel, parent_id) { }; } +function doCommentHide(comment_id) { + return dispatch => { + dispatch({ + type: COMMENT_HIDE_STARTED + }); + return lbryProxy.comment_hide({ + comment_ids: [comment_id] + }).then(result => { + dispatch({ + type: COMMENT_HIDE_COMPLETED, + data: result + }); + }).catch(error => { + dispatch({ + type: COMMENT_HIDE_FAILED, + data: error + }); + dispatch(doToast({ + message: `SDK Errored when trying to hide Comment with comment_id: "${comment_id}"`, + isError: true + })); + }); + }; +} + +function doCommentAbandon(comment_id) { + return dispatch => { + dispatch({ + type: COMMENT_ABANDON_STARTED + }); + return lbryProxy.comment_abandon({ + comment_id: comment_id + }).then(result => { + dispatch({ + type: COMMENT_ABANDON_COMPLETED, + data: { + comment_id: comment_id, + abandoned: result + } + }); + }).catch(error => { + dispatch({ + type: COMMENT_ABANDON_FAILED, + data: error + }); + dispatch(doToast({ + message: `SDK Errored during abandon on Comment w/ ID = "${comment_id}"`, + isError: true + })); + }); + }; +} + +function doCommentUpdate(comment_id, comment) { + // if they provided an empty string, they must have wanted to abandon + if (comment === '') { + return doCommentAbandon(comment_id); + } else { + return dispatch => { + dispatch({ + type: COMMENT_UPDATE_STARTED + }); + return lbryProxy.comment_update({ + comment_id: comment_id, + comment: comment + }).then(result => { + dispatch({ + type: COMMENT_UPDATE_COMPLETED, + data: { + comment: result + } + }); + }).catch(error => { + dispatch({ type: COMMENT_UPDATE_FAILED, data: error }); + dispatch(doToast({ + message: `SDK Errored during update on Comment w/ ID = ${comment_id}`, + isError: true + })); + }); + }; + } +} + // const doToggleBlockChannel = uri => ({ @@ -4616,7 +4692,11 @@ const commentReducer = handleActions({ const commentsByUri = Object.assign({}, state.commentsByUri); if (comments) { + // we use an Array to preserve order of listing + // in reality this doesn't matter and we can just + // sort comments by their timestamp const commentIds = Array(comments.length); + // map the comment_ids to the new comments for (let i = 0; i < comments.length; i++) { commentIds[i] = comments[i].comment_id; @@ -4640,27 +4720,64 @@ const commentReducer = handleActions({ [COMMENT_ABANDON_STARTED]: (state, action) => _extends$7({}, state, { isLoading: true }), - [COMMENT_ABANDON_COMPLETED]: (state, action) => _extends$7({}, state, { - isLoading: false - }), + // remove the existing comment from the id -> comment list and claim -> commentIds + [COMMENT_ABANDON_COMPLETED]: (state, action) => { + const { comment_id, abandoned } = action.data; + const commentById = Object.assign({}, state.commentById); + const byId = Object.assign({}, state.byId); + + if (abandoned && comment_id in abandoned) { + // messy but necessary for the time being + const comment = commentById[comment_id]; + const commentIds = byId[comment.claim_id]; + byId[comment.claim_id] = commentIds.filter(commentId => commentId !== comment_id); + + Object.keys(commentById).forEach(commentId => { + if (commentId === comment_id) { + delete commentById[commentId]; + } + }); + } + return _extends$7({}, state, { + commentById, + byId, + isLoading: false + }); + }, + // do nothing [COMMENT_ABANDON_FAILED]: (state, action) => _extends$7({}, state, { isLoading: false }), - [COMMENT_EDIT_STARTED]: (state, action) => _extends$7({}, state, { + // do nothing + [COMMENT_UPDATE_STARTED]: (state, action) => _extends$7({}, state, { isLoading: true }), - [COMMENT_EDIT_COMPLETED]: (state, action) => _extends$7({}, state, { - isLoading: false - }), - [COMMENT_EDIT_FAILED]: (state, action) => _extends$7({}, state, { + // replace existing comment with comment returned here under its comment_id + [COMMENT_UPDATE_COMPLETED]: (state, action) => { + const { comment } = action.data; + const commentById = Object.assign({}, state.commentById); + + if (comment) { + commentById[comment.comment_id] = comment; + } + + return _extends$7({}, state, { + commentById, + isLoading: false + }); + }, + // nothing can be done here + [COMMENT_UPDATE_FAILED]: (state, action) => _extends$7({}, state, { isLoading: false }), + // nothing can really be done here [COMMENT_HIDE_STARTED]: (state, action) => _extends$7({}, state, { isLoading: true }), - [COMMENT_HIDE_COMPLETED]: (state, action) => _extends$7({}, state, { + [COMMENT_HIDE_COMPLETED]: (state, action) => _extends$7({}, state, { // todo: add HiddenComments state & create selectors isLoading: false }), + // nothing can be done here [COMMENT_HIDE_FAILED]: (state, action) => _extends$7({}, state, { isLoading: false }) @@ -5502,6 +5619,8 @@ const walletReducer = handleActions({ }) }, defaultState$a); +// + const selectState$6 = state => state.content || {}; const makeSelectContentPositionForUri = uri => reselect.createSelector(selectState$6, makeSelectClaimForUri(uri), (state, claim) => { @@ -5666,8 +5785,11 @@ exports.doCheckPendingPublishes = doCheckPendingPublishes; exports.doClaimSearch = doClaimSearch; exports.doClearPublish = doClearPublish; exports.doClearSupport = doClearSupport; +exports.doCommentAbandon = doCommentAbandon; exports.doCommentCreate = doCommentCreate; +exports.doCommentHide = doCommentHide; exports.doCommentList = doCommentList; +exports.doCommentUpdate = doCommentUpdate; exports.doCreateChannel = doCreateChannel; exports.doDeletePurchasedUri = doDeletePurchasedUri; exports.doDeleteTag = doDeleteTag; diff --git a/dist/flow-typed/Lbry.js b/dist/flow-typed/Lbry.js index 92ce9dd..408beb0 100644 --- a/dist/flow-typed/Lbry.js +++ b/dist/flow-typed/Lbry.js @@ -125,7 +125,7 @@ declare type ChannelUpdateResponse = GenericTxResponse & { }; declare type CommentCreateResponse = Comment; -declare type CommentEditResponse = Comment; +declare type CommentUpdateResponse = Comment; declare type CommentListResponse = { items: Array, @@ -254,6 +254,10 @@ declare type LbryTypes = { // Commenting comment_list: (params: {}) => Promise, comment_create: (params: {}) => Promise, + comment_update: (params: {}) => Promise, + comment_hide: (params: {}) => Promise, + comment_abandon: (params: {}) => Promise, + // Wallet utilities wallet_balance: (params: {}) => Promise, wallet_decrypt: (prams: {}) => Promise, diff --git a/flow-typed/Lbry.js b/flow-typed/Lbry.js index 8afe66f..408beb0 100644 --- a/flow-typed/Lbry.js +++ b/flow-typed/Lbry.js @@ -254,6 +254,10 @@ declare type LbryTypes = { // Commenting comment_list: (params: {}) => Promise, comment_create: (params: {}) => Promise, + comment_update: (params: {}) => Promise, + comment_hide: (params: {}) => Promise, + comment_abandon: (params: {}) => Promise, + // Wallet utilities wallet_balance: (params: {}) => Promise, wallet_decrypt: (prams: {}) => Promise, diff --git a/src/index.js b/src/index.js index 65f1db9..98c6e8a 100644 --- a/src/index.js +++ b/src/index.js @@ -121,7 +121,13 @@ export { export { doToggleTagFollow, doAddTag, doDeleteTag } from 'redux/actions/tags'; -export { doCommentList, doCommentCreate } from 'redux/actions/comments'; +export { + doCommentList, + doCommentCreate, + doCommentAbandon, + doCommentHide, + doCommentUpdate, +} from 'redux/actions/comments'; export { doToggleBlockChannel } from 'redux/actions/blocked'; diff --git a/src/redux/actions/comments.js b/src/redux/actions/comments.js index a56b5a1..48f4bad 100644 --- a/src/redux/actions/comments.js +++ b/src/redux/actions/comments.js @@ -43,7 +43,7 @@ export function doCommentCreate( comment: string = '', claim_id: string = '', channel: ?string, - parent_id?: string, + parent_id?: string ) { return (dispatch: Dispatch, getState: GetState) => { const state = getState(); @@ -60,7 +60,7 @@ export function doCommentCreate( channel_id: channel_id, parent_id: parent_id, }) - .then((result: Comment) => { + .then((result: CommentCreateResponse) => { dispatch({ type: ACTIONS.COMMENT_CREATE_COMPLETED, data: { @@ -83,3 +83,98 @@ export function doCommentCreate( }); }; } + +export function doCommentHide(comment_id: string) { + return (dispatch: Dispatch) => { + dispatch({ + type: ACTIONS.COMMENT_HIDE_STARTED, + }); + return Lbry.comment_hide({ + comment_ids: [comment_id], + }) + .then((result: CommentHideResponse) => { + dispatch({ + type: ACTIONS.COMMENT_HIDE_COMPLETED, + data: result, + }); + }) + .catch(error => { + dispatch({ + type: ACTIONS.COMMENT_HIDE_FAILED, + data: error, + }); + dispatch( + doToast({ + message: `SDK Errored when trying to hide Comment with comment_id: "${comment_id}"`, + isError: true, + }) + ); + }); + }; +} + +export function doCommentAbandon(comment_id: string) { + return (dispatch: Dispatch) => { + dispatch({ + type: ACTIONS.COMMENT_ABANDON_STARTED, + }); + return Lbry.comment_abandon({ + comment_id: comment_id, + }) + .then((result: CommentAbandonResponse) => { + dispatch({ + type: ACTIONS.COMMENT_ABANDON_COMPLETED, + data: { + comment_id: comment_id, + abandoned: result, + }, + }); + }) + .catch(error => { + dispatch({ + type: ACTIONS.COMMENT_ABANDON_FAILED, + data: error, + }); + dispatch( + doToast({ + message: `SDK Errored during abandon on Comment w/ ID = "${comment_id}"`, + isError: true, + }) + ); + }); + }; +} + +export function doCommentUpdate(comment_id: string, comment: string) { + // if they provided an empty string, they must have wanted to abandon + if (comment === '') { + return doCommentAbandon(comment_id); + } else { + return (dispatch: Dispatch) => { + dispatch({ + type: ACTIONS.COMMENT_UPDATE_STARTED, + }); + return Lbry.comment_update({ + comment_id: comment_id, + comment: comment, + }) + .then((result: CommentUpdateResponse) => { + dispatch({ + type: ACTIONS.COMMENT_UPDATE_COMPLETED, + data: { + comment: result, + }, + }); + }) + .catch(error => { + dispatch({ type: ACTIONS.COMMENT_UPDATE_FAILED, data: error }); + dispatch( + doToast({ + message: `SDK Errored during update on Comment w/ ID = ${comment_id}`, + isError: true, + }) + ); + }); + }; + } +} From c30a8ec66c0d5692cc93ef8adeb95ba830c857f8 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Mon, 13 Jan 2020 17:04:41 -0500 Subject: [PATCH 15/34] Add todos --- src/redux/selectors/comments.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/redux/selectors/comments.js b/src/redux/selectors/comments.js index 048e7f2..86286ea 100644 --- a/src/redux/selectors/comments.js +++ b/src/redux/selectors/comments.js @@ -63,3 +63,6 @@ export const makeSelectCommentsForUri = (uri: string) => return byClaimId && byClaimId[claimId]; } ); + +// todo: allow SDK to retrieve user comments through comment_list +// todo: implement selectors for selecting comments owned by user From fd0d097c91fb6132ba614114ad5ee268c9f05951 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Sun, 19 Jan 2020 21:27:36 -0500 Subject: [PATCH 16/34] Cleanup --- dist/bundle.es.js | 31 ++++++++++++++++++++----------- src/redux/actions/comments.js | 6 +++--- src/redux/reducers/comments.js | 6 +----- src/redux/selectors/comments.js | 4 +--- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 9e3c5e6..c80a7e8 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -1246,6 +1246,18 @@ function buildURI(UrlObj, includeProto = true, protoDefault = 'lbry://') { deprecatedParts = _objectWithoutProperties(UrlObj, ['streamName', 'streamClaimId', 'channelName', 'channelClaimId', 'primaryClaimSequence', 'primaryBidPosition', 'secondaryClaimSequence', 'secondaryBidPosition']); const { claimId, claimName, contentName } = deprecatedParts; + { + if (claimId) { + console.error(__("'claimId' should no longer be used. Use 'streamClaimId' or 'channelClaimId' instead")); + } + if (claimName) { + console.error(__("'claimName' should no longer be used. Use 'streamClaimName' or 'channelClaimName' instead")); + } + if (contentName) { + console.error(__("'contentName' should no longer be used. Use 'streamName' instead")); + } + } + if (!claimName && !channelName && !streamName) { console.error(__("'claimName', 'channelName', and 'streamName' are all empty. One must be present to build a url.")); } @@ -4166,7 +4178,7 @@ function doCommentHide(comment_id) { data: error }); dispatch(doToast({ - message: `SDK Errored when trying to hide Comment with comment_id: "${comment_id}"`, + message: 'There was an error hiding this comment. Please try again later.', isError: true })); }); @@ -4194,7 +4206,7 @@ function doCommentAbandon(comment_id) { data: error }); dispatch(doToast({ - message: `SDK Errored during abandon on Comment w/ ID = "${comment_id}"`, + message: 'There was an error hiding this comment. Please try again later.', isError: true })); }); @@ -4223,7 +4235,7 @@ function doCommentUpdate(comment_id, comment) { }).catch(error => { dispatch({ type: COMMENT_UPDATE_FAILED, data: error }); dispatch(doToast({ - message: `SDK Errored during update on Comment w/ ID = ${comment_id}`, + message: 'There was an error hiding this comment. Please try again later.', isError: true })); }); @@ -4732,11 +4744,7 @@ const commentReducer = handleActions({ const commentIds = byId[comment.claim_id]; byId[comment.claim_id] = commentIds.filter(commentId => commentId !== comment_id); - Object.keys(commentById).forEach(commentId => { - if (commentId === comment_id) { - delete commentById[commentId]; - } - }); + delete commentById[comment_id]; } return _extends$7({}, state, { commentById, @@ -5668,12 +5676,10 @@ const selectCommentsByClaimId = reselect.createSelector(selectState$8, selectCom const byClaimId = state.byId || {}; const comments = {}; - // for every claimId -> commentId, put comments in the object + // replace every comment_id in the list with the actual comment object Object.keys(byClaimId).forEach(claimId => { - // get all the commentIds that commented on this ClaimId const commentIds = byClaimId[claimId]; - // map a new array of comments by the claimId comments[claimId] = Array(commentIds === null ? 0 : commentIds.length); for (let i = 0; i < commentIds.length; i++) { comments[claimId][i] = byId[commentIds[i]]; @@ -5708,6 +5714,9 @@ const makeSelectCommentsForUri = uri => reselect.createSelector(selectCommentsBy return byClaimId && byClaimId[claimId]; }); +// todo: allow SDK to retrieve user comments through comment_list +// todo: implement selectors for selecting comments owned by user + // const selectState$9 = state => state.tags || {}; diff --git a/src/redux/actions/comments.js b/src/redux/actions/comments.js index 48f4bad..01c79b2 100644 --- a/src/redux/actions/comments.js +++ b/src/redux/actions/comments.js @@ -105,7 +105,7 @@ export function doCommentHide(comment_id: string) { }); dispatch( doToast({ - message: `SDK Errored when trying to hide Comment with comment_id: "${comment_id}"`, + message: 'There was an error hiding this comment. Please try again later.', isError: true, }) ); @@ -137,7 +137,7 @@ export function doCommentAbandon(comment_id: string) { }); dispatch( doToast({ - message: `SDK Errored during abandon on Comment w/ ID = "${comment_id}"`, + message: 'There was an error hiding this comment. Please try again later.', isError: true, }) ); @@ -170,7 +170,7 @@ export function doCommentUpdate(comment_id: string, comment: string) { dispatch({ type: ACTIONS.COMMENT_UPDATE_FAILED, data: error }); dispatch( doToast({ - message: `SDK Errored during update on Comment w/ ID = ${comment_id}`, + message: 'There was an error hiding this comment. Please try again later.', isError: true, }) ); diff --git a/src/redux/reducers/comments.js b/src/redux/reducers/comments.js index 8876b0e..c45edd0 100644 --- a/src/redux/reducers/comments.js +++ b/src/redux/reducers/comments.js @@ -97,11 +97,7 @@ export const commentReducer = handleActions( const commentIds = byId[comment.claim_id]; byId[comment.claim_id] = commentIds.filter(commentId => commentId !== comment_id); - Object.keys(commentById).forEach(commentId => { - if (commentId === comment_id) { - delete commentById[commentId]; - } - }); + delete commentById[comment_id]; } return { ...state, diff --git a/src/redux/selectors/comments.js b/src/redux/selectors/comments.js index 86286ea..c3a2f2d 100644 --- a/src/redux/selectors/comments.js +++ b/src/redux/selectors/comments.js @@ -15,12 +15,10 @@ export const selectCommentsByClaimId = createSelector( const byClaimId = state.byId || {}; const comments = {}; - // for every claimId -> commentId, put comments in the object + // replace every comment_id in the list with the actual comment object Object.keys(byClaimId).forEach(claimId => { - // get all the commentIds that commented on this ClaimId const commentIds = byClaimId[claimId]; - // map a new array of comments by the claimId comments[claimId] = Array(commentIds === null ? 0 : commentIds.length); for (let i = 0; i < commentIds.length; i++) { comments[claimId][i] = byId[commentIds[i]]; From bc2436dce28eec09a268afb4b896421ec718443f Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Tue, 21 Jan 2020 00:46:14 -0500 Subject: [PATCH 17/34] Corrects abandon return type & fixes issue where redux wasn't being changed --- dist/bundle.es.js | 62 +++++++++++++++++++--------------- dist/flow-typed/Lbry.js | 2 +- flow-typed/Lbry.js | 2 +- src/redux/actions/comments.js | 21 ++++++++---- src/redux/reducers/comments.js | 19 ++++++----- 5 files changed, 61 insertions(+), 45 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index c915b8b..16deb2d 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -4067,7 +4067,7 @@ const doUpdateSearchOptions = newOptions => (dispatch, getState) => { } }; -// +// function savePosition(claimId, outpoint, position) { return dispatch => { @@ -4204,13 +4204,20 @@ function doCommentAbandon(comment_id) { return lbryProxy.comment_abandon({ comment_id: comment_id }).then(result => { - dispatch({ - type: COMMENT_ABANDON_COMPLETED, - data: { - comment_id: comment_id, - abandoned: result - } - }); + // Comment may not be deleted if the signing channel can't be signed. + // This will happen if the channel was recently created or abandoned. + if (result.abandoned) { + dispatch({ + type: COMMENT_ABANDON_COMPLETED, + data: { + comment_id: comment_id + } + }); + } else { + dispatch({ + type: COMMENT_ABANDON_FAILED + }); + } }).catch(error => { dispatch({ type: COMMENT_ABANDON_FAILED, @@ -4740,35 +4747,36 @@ const commentReducer = handleActions({ [COMMENT_LIST_FAILED]: (state, action) => _extends$8({}, state, { isLoading: false }), - [COMMENT_ABANDON_STARTED]: (state, action) => _extends$7({}, state, { + [COMMENT_ABANDON_STARTED]: (state, action) => _extends$8({}, state, { isLoading: true }), - // remove the existing comment from the id -> comment list and claim -> commentIds [COMMENT_ABANDON_COMPLETED]: (state, action) => { - const { comment_id, abandoned } = action.data; + const { comment_id } = action.data; const commentById = Object.assign({}, state.commentById); const byId = Object.assign({}, state.byId); - if (abandoned && comment_id in abandoned) { - // messy but necessary for the time being - const comment = commentById[comment_id]; - const commentIds = byId[comment.claim_id]; - byId[comment.claim_id] = commentIds.filter(commentId => commentId !== comment_id); - - delete commentById[comment_id]; + // to remove the comment and its references + const claimId = commentById[comment_id].claim_id; + for (let i = 0; i < byId[claimId].length; i++) { + if (byId[claimId][i] === comment_id) { + byId[claimId].splice(i, 1); + break; + } } - return _extends$7({}, state, { + delete commentById[comment_id]; + + return _extends$8({}, state, { commentById, byId, isLoading: false }); }, // do nothing - [COMMENT_ABANDON_FAILED]: (state, action) => _extends$7({}, state, { + [COMMENT_ABANDON_FAILED]: (state, action) => _extends$8({}, state, { isLoading: false }), // do nothing - [COMMENT_UPDATE_STARTED]: (state, action) => _extends$7({}, state, { + [COMMENT_UPDATE_STARTED]: (state, action) => _extends$8({}, state, { isLoading: true }), // replace existing comment with comment returned here under its comment_id @@ -4780,24 +4788,24 @@ const commentReducer = handleActions({ commentById[comment.comment_id] = comment; } - return _extends$7({}, state, { + return _extends$8({}, state, { commentById, isLoading: false }); }, // nothing can be done here - [COMMENT_UPDATE_FAILED]: (state, action) => _extends$7({}, state, { + [COMMENT_UPDATE_FAILED]: (state, action) => _extends$8({}, state, { isLoading: false }), // nothing can really be done here - [COMMENT_HIDE_STARTED]: (state, action) => _extends$7({}, state, { + [COMMENT_HIDE_STARTED]: (state, action) => _extends$8({}, state, { isLoading: true }), - [COMMENT_HIDE_COMPLETED]: (state, action) => _extends$7({}, state, { // todo: add HiddenComments state & create selectors + [COMMENT_HIDE_COMPLETED]: (state, action) => _extends$8({}, state, { // todo: add HiddenComments state & create selectors isLoading: false }), // nothing can be done here - [COMMENT_HIDE_FAILED]: (state, action) => _extends$7({}, state, { + [COMMENT_HIDE_FAILED]: (state, action) => _extends$8({}, state, { isLoading: false }) }, defaultState$1); @@ -5638,7 +5646,7 @@ const walletReducer = handleActions({ }) }, defaultState$a); -// +// const selectState$6 = state => state.content || {}; diff --git a/dist/flow-typed/Lbry.js b/dist/flow-typed/Lbry.js index 408beb0..d2657cb 100644 --- a/dist/flow-typed/Lbry.js +++ b/dist/flow-typed/Lbry.js @@ -142,7 +142,7 @@ declare type CommentHideResponse = { declare type CommentAbandonResponse = { // keyed by the CommentId given - [string]: { abandoned: boolean }, + abandoned: boolean, }; declare type ChannelListResponse = { diff --git a/flow-typed/Lbry.js b/flow-typed/Lbry.js index 408beb0..d2657cb 100644 --- a/flow-typed/Lbry.js +++ b/flow-typed/Lbry.js @@ -142,7 +142,7 @@ declare type CommentHideResponse = { declare type CommentAbandonResponse = { // keyed by the CommentId given - [string]: { abandoned: boolean }, + abandoned: boolean, }; declare type ChannelListResponse = { diff --git a/src/redux/actions/comments.js b/src/redux/actions/comments.js index 01c79b2..4441651 100644 --- a/src/redux/actions/comments.js +++ b/src/redux/actions/comments.js @@ -122,13 +122,20 @@ export function doCommentAbandon(comment_id: string) { comment_id: comment_id, }) .then((result: CommentAbandonResponse) => { - dispatch({ - type: ACTIONS.COMMENT_ABANDON_COMPLETED, - data: { - comment_id: comment_id, - abandoned: result, - }, - }); + // Comment may not be deleted if the signing channel can't be signed. + // This will happen if the channel was recently created or abandoned. + if (result.abandoned) { + dispatch({ + type: ACTIONS.COMMENT_ABANDON_COMPLETED, + data: { + comment_id: comment_id, + }, + }); + } else { + dispatch({ + type: ACTIONS.COMMENT_ABANDON_FAILED, + }); + } }) .catch(error => { dispatch({ diff --git a/src/redux/reducers/comments.js b/src/redux/reducers/comments.js index c45edd0..493d225 100644 --- a/src/redux/reducers/comments.js +++ b/src/redux/reducers/comments.js @@ -85,20 +85,21 @@ export const commentReducer = handleActions( ...state, isLoading: true, }), - // remove the existing comment from the id -> comment list and claim -> commentIds [ACTIONS.COMMENT_ABANDON_COMPLETED]: (state: CommentsState, action: any) => { - const { comment_id, abandoned } = action.data; + const { comment_id } = action.data; const commentById = Object.assign({}, state.commentById); const byId = Object.assign({}, state.byId); - if (abandoned && comment_id in abandoned) { - // messy but necessary for the time being - const comment: Comment = commentById[comment_id]; - const commentIds = byId[comment.claim_id]; - byId[comment.claim_id] = commentIds.filter(commentId => commentId !== comment_id); - - delete commentById[comment_id]; + // to remove the comment and its references + const claimId = commentById[comment_id].claim_id; + for (let i = 0; i < byId[claimId].length; i++) { + if (byId[claimId][i] === comment_id) { + byId[claimId].splice(i, 1); + break; + } } + delete commentById[comment_id]; + return { ...state, commentById, From 11840e01b64515a015a8dcd495ea84e70ee9e21c Mon Sep 17 00:00:00 2001 From: jessop Date: Thu, 9 Jan 2020 21:36:18 -0500 Subject: [PATCH 18/34] channel list will no longer overwrite resolved claims byId --- dist/bundle.es.js | 4 +++- src/redux/reducers/claims.js | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 4163f5b..9ae6b9d 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -4319,7 +4319,9 @@ reducers[FETCH_CHANNEL_LIST_COMPLETED] = (state, action) => { claims.forEach(claim => { // $FlowFixMe myChannelClaims.add(claim.claim_id); - byId[claim.claim_id] = claim; + if (!byId[claim.claim_id]) { + byId[claim.claim_id] = claim; + } if (pendingById[claim.claim_id] && claim.confirmations > 0) { delete pendingById[claim.claim_id]; diff --git a/src/redux/reducers/claims.js b/src/redux/reducers/claims.js index 8e6b121..f60cdca 100644 --- a/src/redux/reducers/claims.js +++ b/src/redux/reducers/claims.js @@ -216,7 +216,9 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): St claims.forEach(claim => { // $FlowFixMe myChannelClaims.add(claim.claim_id); - byId[claim.claim_id] = claim; + if (!byId[claim.claim_id]) { + byId[claim.claim_id] = claim; + } if (pendingById[claim.claim_id] && claim.confirmations > 0) { delete pendingById[claim.claim_id]; @@ -265,7 +267,8 @@ reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED] = (state: State, action: any): const paginatedClaimsByChannel = Object.assign({}, state.paginatedClaimsByChannel); // check if count has changed - that means cached pagination will be wrong, so clear it const previousCount = paginatedClaimsByChannel[uri] && paginatedClaimsByChannel[uri]['itemCount']; - const byChannel = (claimsInChannel === previousCount) ? Object.assign({}, paginatedClaimsByChannel[uri]) : {}; + const byChannel = + claimsInChannel === previousCount ? Object.assign({}, paginatedClaimsByChannel[uri]) : {}; const allClaimIds = new Set(byChannel.all); const currentPageClaimIds = []; const byId = Object.assign({}, state.byId); From 17a5260c3fb23e74dd7ac8fd8a2e7beaf60afac8 Mon Sep 17 00:00:00 2001 From: Akinwale Ariwodola Date: Wed, 22 Jan 2020 02:04:50 +0100 Subject: [PATCH 19/34] add doResolvedSearch actions which returns resolved search results (#258) * add doResolvedSearch actions which returns resolved search results * add recommended content selector * update ResolvedSearchResult type * support for multiple pages of resolved search results --- dist/bundle.es.js | 154 +++++++++++++++++++++++++++++++--- dist/flow-typed/Search.js | 25 ++++++ flow-typed/Search.js | 25 ++++++ src/constants/action_types.js | 3 + src/constants/tags.js | 2 +- src/index.js | 6 ++ src/redux/actions/search.js | 72 ++++++++++++++++ src/redux/reducers/search.js | 43 ++++++++++ src/redux/selectors/claims.js | 41 ++++++++- src/redux/selectors/search.js | 32 +++++++ 10 files changed, 388 insertions(+), 15 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 4163f5b..0549d59 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -15,7 +15,6 @@ const CHANNEL_NEW = 'new'; const PAGE_SIZE = 20; var claim = /*#__PURE__*/Object.freeze({ - __proto__: null, MINIMUM_PUBLISH_BID: MINIMUM_PUBLISH_BID, CHANNEL_ANONYMOUS: CHANNEL_ANONYMOUS, CHANNEL_NEW: CHANNEL_NEW, @@ -163,6 +162,9 @@ const DELETE_PURCHASED_URI = 'DELETE_PURCHASED_URI'; const SEARCH_START = 'SEARCH_START'; const SEARCH_SUCCESS = 'SEARCH_SUCCESS'; const SEARCH_FAIL = 'SEARCH_FAIL'; +const RESOLVED_SEARCH_START = 'RESOLVED_SEARCH_START'; +const RESOLVED_SEARCH_SUCCESS = 'RESOLVED_SEARCH_SUCCESS'; +const RESOLVED_SEARCH_FAIL = 'RESOLVED_SEARCH_FAIL'; const UPDATE_SEARCH_QUERY = 'UPDATE_SEARCH_QUERY'; const UPDATE_SEARCH_OPTIONS = 'UPDATE_SEARCH_OPTIONS'; const UPDATE_SEARCH_SUGGESTIONS = 'UPDATE_SEARCH_SUGGESTIONS'; @@ -275,7 +277,6 @@ const TOGGLE_BLOCK_CHANNEL = 'TOGGLE_BLOCK_CHANNEL'; const USER_STATE_POPULATE = 'USER_STATE_POPULATE'; var action_types = /*#__PURE__*/Object.freeze({ - __proto__: null, WINDOW_FOCUSED: WINDOW_FOCUSED, DAEMON_READY: DAEMON_READY, DAEMON_VERSION_MATCH: DAEMON_VERSION_MATCH, @@ -403,6 +404,9 @@ var action_types = /*#__PURE__*/Object.freeze({ SEARCH_START: SEARCH_START, SEARCH_SUCCESS: SEARCH_SUCCESS, SEARCH_FAIL: SEARCH_FAIL, + RESOLVED_SEARCH_START: RESOLVED_SEARCH_START, + RESOLVED_SEARCH_SUCCESS: RESOLVED_SEARCH_SUCCESS, + RESOLVED_SEARCH_FAIL: RESOLVED_SEARCH_FAIL, UPDATE_SEARCH_QUERY: UPDATE_SEARCH_QUERY, UPDATE_SEARCH_OPTIONS: UPDATE_SEARCH_OPTIONS, UPDATE_SEARCH_SUGGESTIONS: UPDATE_SEARCH_SUGGESTIONS, @@ -518,7 +522,6 @@ const OTHER = 'other'; const COPYRIGHT = 'copyright'; var licenses = /*#__PURE__*/Object.freeze({ - __proto__: null, CC_LICENSES: CC_LICENSES, NONE: NONE, PUBLIC_DOMAIN: PUBLIC_DOMAIN, @@ -549,7 +552,6 @@ const HISTORY = 'user_history'; const WALLET = 'wallet'; var pages = /*#__PURE__*/Object.freeze({ - __proto__: null, AUTH: AUTH, BACKUP: BACKUP, CHANNEL: CHANNEL, @@ -599,7 +601,6 @@ const RECEIVE_INTERESTS_NOTIFICATIONS = 'receiveInterestsNotifications'; const RECEIVE_CREATOR_NOTIFICATIONS = 'receiveCreatorNotifications'; var settings = /*#__PURE__*/Object.freeze({ - __proto__: null, CREDIT_REQUIRED_ACKNOWLEDGED: CREDIT_REQUIRED_ACKNOWLEDGED, NEW_USER_ACKNOWLEDGED: NEW_USER_ACKNOWLEDGED, EMAIL_COLLECTION_ACKNOWLEDGED: EMAIL_COLLECTION_ACKNOWLEDGED, @@ -627,7 +628,6 @@ const TITLE = 'title'; const FILENAME = 'filename'; var sort_options = /*#__PURE__*/Object.freeze({ - __proto__: null, DATE_NEW: DATE_NEW, DATE_OLD: DATE_OLD, TITLE: TITLE, @@ -641,7 +641,6 @@ const COMPLETE = 'complete'; const MANUAL = 'manual'; var thumbnail_upload_statuses = /*#__PURE__*/Object.freeze({ - __proto__: null, API_DOWN: API_DOWN, READY: READY, IN_PROGRESS: IN_PROGRESS, @@ -661,7 +660,6 @@ const UPDATE = 'update'; const ABANDON = 'abandon'; var transaction_types = /*#__PURE__*/Object.freeze({ - __proto__: null, ALL: ALL, SPEND: SPEND, RECEIVE: RECEIVE, @@ -678,7 +676,6 @@ const PAGE_SIZE$1 = 50; const LATEST_PAGE_SIZE = 20; var transaction_list = /*#__PURE__*/Object.freeze({ - __proto__: null, PAGE_SIZE: PAGE_SIZE$1, LATEST_PAGE_SIZE: LATEST_PAGE_SIZE }); @@ -687,7 +684,6 @@ const SPEECH_STATUS = 'https://spee.ch/api/config/site/publishing'; const SPEECH_PUBLISH = 'https://spee.ch/api/claim/publish'; var speech_urls = /*#__PURE__*/Object.freeze({ - __proto__: null, SPEECH_STATUS: SPEECH_STATUS, SPEECH_PUBLISH: SPEECH_PUBLISH }); @@ -733,7 +729,6 @@ const WALLET_DIR = 'wallet_dir'; const WALLETS = 'wallets'; var daemon_settings = /*#__PURE__*/Object.freeze({ - __proto__: null, ANNOUNCE_HEAD_AND_SD_ONLY: ANNOUNCE_HEAD_AND_SD_ONLY, API: API, BLOB_DOWNLOAD_TIMEOUT: BLOB_DOWNLOAD_TIMEOUT, @@ -787,7 +782,6 @@ var daemon_settings = /*#__PURE__*/Object.freeze({ const WALLET_SERVERS = LBRYUM_SERVERS; var shared_preferences = /*#__PURE__*/Object.freeze({ - __proto__: null, WALLET_SERVERS: WALLET_SERVERS }); @@ -1342,6 +1336,18 @@ const makeSelectSearchUris = query => // replace statement below is kind of ugly, and repeated in doSearch action reselect.createSelector(selectSearchUrisByQuery, byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query]); +const selectResolvedSearchResultsByQuery = reselect.createSelector(selectState, state => state.resolvedResultsByQuery); + +const selectResolvedSearchResultsByQueryLastPageReached = reselect.createSelector(selectState, state => state.resolvedResultsByQueryLastPageReached); + +const makeSelectResolvedSearchResults = query => +// replace statement below is kind of ugly, and repeated in doSearch action +reselect.createSelector(selectResolvedSearchResultsByQuery, byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query]); + +const makeSelectResolvedSearchResultsLastPageReached = query => +// replace statement below is kind of ugly, and repeated in doSearch action +reselect.createSelector(selectResolvedSearchResultsByQueryLastPageReached, byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query]); + const selectSearchBarFocused = reselect.createSelector(selectState, state => state.focused); const selectSearchSuggestions = reselect.createSelector(selectSearchValue, selectSuggestions, (query, suggestions) => { @@ -2277,6 +2283,34 @@ const makeSelectMyStreamUrlsForPage = (page = 1) => reselect.createSelector(sele const selectMyStreamUrlsCount = reselect.createSelector(selectMyClaimUrisWithoutChannels, channels => channels.length); +const makeSelectResolvedRecommendedContentForUri = (uri, size) => reselect.createSelector(makeSelectClaimForUri(uri), selectResolvedSearchResultsByQuery, (claim, resolvedResultsByQuery) => { + const atVanityURI = !uri.includes('#'); + + let recommendedContent; + if (claim) { + // always grab full URL - this can change once search returns canonical + const currentUri = buildURI({ streamClaimId: claim.claim_id, streamName: claim.name }); + + const { title } = claim.value; + + if (!title) { + return; + } + + const searchQuery = getSearchQueryString(title.replace(/\//, ' '), { size }, undefined, { + related_to: claim.claim_id + }); + + let results = resolvedResultsByQuery[searchQuery]; + if (results) { + results = results.filter(result => buildURI({ streamClaimId: result.claimId, streamName: result.name }) !== currentUri); + recommendedContent = results; + } + } + + return recommendedContent; +}); + function numberWithCommas(x) { var parts = x.toString().split('.'); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); @@ -4020,6 +4054,63 @@ from, isBackgroundSearch = false, options = {}, resolveResults = true) => (dispa }); }; +const doResolvedSearch = (rawQuery, size, // only pass in if you don't want to use the users setting (ex: related content) +from, isBackgroundSearch = false, options = {}) => (dispatch, getState) => { + const query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' '); + + if (!query) { + dispatch({ + type: RESOLVED_SEARCH_FAIL + }); + return; + } + + const state = getState(); + let queryWithOptions = makeSelectQueryWithOptions(query, size, from, isBackgroundSearch, options)(state); + + // make from null so that we can maintain a reference to the same query for multiple pages and simply append the found results + let queryWithoutFrom = makeSelectQueryWithOptions(query, size, null, isBackgroundSearch, options)(state); + + // If we have already searched for something, we don't need to do anything + // TODO: Tweak this check for multiple page results + /* const resultsForQuery = makeSelectResolvedSearchResults(queryWithOptions)(state); + if (resultsForQuery && resultsForQuery.length && resultsForQuery.length > (from * size)) { + return; + } */ + + dispatch({ + type: RESOLVED_SEARCH_START + }); + + if (!state.search.searchQuery && !isBackgroundSearch) { + dispatch(doUpdateSearchQuery(query)); + } + + fetch(`${CONNECTION_STRING}search?resolve=true&${queryWithOptions}`).then(handleFetchResponse).then(data => { + const results = []; + + data.forEach(result => { + if (result) { + results.push(result); + } + }); + + dispatch({ + type: RESOLVED_SEARCH_SUCCESS, + data: { + query: queryWithoutFrom, + results, + pageSize: size, + append: parseInt(from, 10) > parseInt(size, 10) - 1 + } + }); + }).catch(e => { + dispatch({ + type: RESOLVED_SEARCH_FAIL + }); + }); +}; + const doFocusSearchInput = () => dispatch => dispatch({ type: SEARCH_FOCUS }); @@ -5024,7 +5115,9 @@ const defaultState$7 = { [SEARCH_OPTIONS.MEDIA_APPLICATION]: true }, suggestions: {}, - urisByQuery: {} + urisByQuery: {}, + resolvedResultsByQuery: {}, + resolvedResultsByQueryLastPageReached: {} }; const searchReducer = handleActions({ @@ -5044,6 +5137,35 @@ const searchReducer = handleActions({ searching: false }), + [RESOLVED_SEARCH_START]: state => _extends$d({}, state, { + searching: true + }), + [RESOLVED_SEARCH_SUCCESS]: (state, action) => { + const resolvedResultsByQuery = Object.assign({}, state.resolvedResultsByQuery); + const resolvedResultsByQueryLastPageReached = Object.assign({}, state.resolvedResultsByQueryLastPageReached); + const { append, query, results, pageSize } = action.data; + + if (append) { + // todo: check for duplicates when concatenating? + resolvedResultsByQuery[query] = resolvedResultsByQuery[query] && resolvedResultsByQuery[query].length ? resolvedResultsByQuery[query].concat(results) : results; + } else { + resolvedResultsByQuery[query] = results; + } + + // the returned number of urls is less than the page size, so we're on the last page + resolvedResultsByQueryLastPageReached[query] = results.length < pageSize; + + return _extends$d({}, state, { + searching: false, + resolvedResultsByQuery, + resolvedResultsByQueryLastPageReached + }); + }, + + [RESOLVED_SEARCH_FAIL]: state => _extends$d({}, state, { + searching: false + }), + [UPDATE_SEARCH_QUERY]: (state, action) => _extends$d({}, state, { searchQuery: action.data.query, isActive: true @@ -5612,6 +5734,7 @@ exports.doPurchaseUri = doPurchaseUri; exports.doResetThumbnailStatus = doResetThumbnailStatus; exports.doResolveUri = doResolveUri; exports.doResolveUris = doResolveUris; +exports.doResolvedSearch = doResolvedSearch; exports.doSearch = doSearch; exports.doSendDraftTransaction = doSendDraftTransaction; exports.doSendTip = doSendTip; @@ -5680,6 +5803,9 @@ exports.makeSelectPermanentUrlForUri = makeSelectPermanentUrlForUri; exports.makeSelectPublishFormValue = makeSelectPublishFormValue; exports.makeSelectQueryWithOptions = makeSelectQueryWithOptions; exports.makeSelectRecommendedContentForUri = makeSelectRecommendedContentForUri; +exports.makeSelectResolvedRecommendedContentForUri = makeSelectResolvedRecommendedContentForUri; +exports.makeSelectResolvedSearchResults = makeSelectResolvedSearchResults; +exports.makeSelectResolvedSearchResultsLastPageReached = makeSelectResolvedSearchResultsLastPageReached; exports.makeSelectSearchDownloadUrlsCount = makeSelectSearchDownloadUrlsCount; exports.makeSelectSearchDownloadUrlsForPage = makeSelectSearchDownloadUrlsForPage; exports.makeSelectSearchUris = makeSelectSearchUris; @@ -5772,6 +5898,8 @@ exports.selectPurchasedUris = selectPurchasedUris; exports.selectReceiveAddress = selectReceiveAddress; exports.selectRecentTransactions = selectRecentTransactions; exports.selectReservedBalance = selectReservedBalance; +exports.selectResolvedSearchResultsByQuery = selectResolvedSearchResultsByQuery; +exports.selectResolvedSearchResultsByQueryLastPageReached = selectResolvedSearchResultsByQueryLastPageReached; exports.selectResolvingUris = selectResolvingUris; exports.selectSearchBarFocused = selectSearchBarFocused; exports.selectSearchOptions = selectSearchOptions; diff --git a/dist/flow-typed/Search.js b/dist/flow-typed/Search.js index 5fad710..2a2152e 100644 --- a/dist/flow-typed/Search.js +++ b/dist/flow-typed/Search.js @@ -28,6 +28,8 @@ declare type SearchState = { options: SearchOptions, suggestions: { [string]: Array }, urisByQuery: {}, + resolvedResultsByQuery: {}, + resolvedResultsByQueryLastPageReached: {}, }; declare type SearchSuccess = { @@ -57,3 +59,26 @@ declare type UpdateSearchOptions = { type: ACTIONS.UPDATE_SEARCH_OPTIONS, data: SearchOptions, }; + +declare type ResolvedSearchResult = { + channel: string, + channel_claim_id: string, + claimId: string, + duration: number, + fee: number, + name: string, + nsfw: boolean, + release_time: string, + thumbnail_url: string, + title: string, +}; + +declare type ResolvedSearchSuccess = { + type: ACTIONS.RESOLVED_SEARCH_SUCCESS, + data: { + append: boolean, + pageSize: number, + results: Array, + query: string, + }, +}; diff --git a/flow-typed/Search.js b/flow-typed/Search.js index 5fad710..2a2152e 100644 --- a/flow-typed/Search.js +++ b/flow-typed/Search.js @@ -28,6 +28,8 @@ declare type SearchState = { options: SearchOptions, suggestions: { [string]: Array }, urisByQuery: {}, + resolvedResultsByQuery: {}, + resolvedResultsByQueryLastPageReached: {}, }; declare type SearchSuccess = { @@ -57,3 +59,26 @@ declare type UpdateSearchOptions = { type: ACTIONS.UPDATE_SEARCH_OPTIONS, data: SearchOptions, }; + +declare type ResolvedSearchResult = { + channel: string, + channel_claim_id: string, + claimId: string, + duration: number, + fee: number, + name: string, + nsfw: boolean, + release_time: string, + thumbnail_url: string, + title: string, +}; + +declare type ResolvedSearchSuccess = { + type: ACTIONS.RESOLVED_SEARCH_SUCCESS, + data: { + append: boolean, + pageSize: number, + results: Array, + query: string, + }, +}; diff --git a/src/constants/action_types.js b/src/constants/action_types.js index ac23374..42cf987 100644 --- a/src/constants/action_types.js +++ b/src/constants/action_types.js @@ -139,6 +139,9 @@ export const DELETE_PURCHASED_URI = 'DELETE_PURCHASED_URI'; export const SEARCH_START = 'SEARCH_START'; export const SEARCH_SUCCESS = 'SEARCH_SUCCESS'; export const SEARCH_FAIL = 'SEARCH_FAIL'; +export const RESOLVED_SEARCH_START = 'RESOLVED_SEARCH_START'; +export const RESOLVED_SEARCH_SUCCESS = 'RESOLVED_SEARCH_SUCCESS'; +export const RESOLVED_SEARCH_FAIL = 'RESOLVED_SEARCH_FAIL'; export const UPDATE_SEARCH_QUERY = 'UPDATE_SEARCH_QUERY'; export const UPDATE_SEARCH_OPTIONS = 'UPDATE_SEARCH_OPTIONS'; export const UPDATE_SEARCH_SUGGESTIONS = 'UPDATE_SEARCH_SUGGESTIONS'; diff --git a/src/constants/tags.js b/src/constants/tags.js index 9456a81..e44fe37 100644 --- a/src/constants/tags.js +++ b/src/constants/tags.js @@ -510,5 +510,5 @@ export const DEFAULT_KNOWN_TAGS = [ 'portugal', 'dantdm', 'teaser', - 'lbry' + 'lbry', ]; diff --git a/src/index.js b/src/index.js index 65f1db9..b9d554f 100644 --- a/src/index.js +++ b/src/index.js @@ -90,6 +90,7 @@ export { export { doSearch, + doResolvedSearch, doUpdateSearchQuery, doFocusSearchInput, doBlurSearchInput, @@ -183,6 +184,7 @@ export { makeSelectOmittedCountForChannel, makeSelectClaimIsNsfw, makeSelectRecommendedContentForUri, + makeSelectResolvedRecommendedContentForUri, makeSelectFirstRecommendedFileForUri, makeSelectChannelForClaimUri, makeSelectClaimIsPending, @@ -265,9 +267,13 @@ export { export { selectSearchState }; export { makeSelectSearchUris, + makeSelectResolvedSearchResults, + makeSelectResolvedSearchResultsLastPageReached, selectSearchValue, selectSearchOptions, selectIsSearching, + selectResolvedSearchResultsByQuery, + selectResolvedSearchResultsByQueryLastPageReached, selectSearchUrisByQuery, selectSearchBarFocused, selectSearchSuggestions, diff --git a/src/redux/actions/search.js b/src/redux/actions/search.js index 3cd3a47..e00d7ba 100644 --- a/src/redux/actions/search.js +++ b/src/redux/actions/search.js @@ -4,6 +4,7 @@ import { buildURI } from 'lbryURI'; import { doResolveUri } from 'redux/actions/claims'; import { makeSelectSearchUris, + makeSelectResolvedSearchResults, selectSuggestions, makeSelectQueryWithOptions, selectSearchValue, @@ -159,6 +160,77 @@ export const doSearch = ( }); }; +export const doResolvedSearch = ( + rawQuery: string, + size: ?number, // only pass in if you don't want to use the users setting (ex: related content) + from: ?number, + isBackgroundSearch: boolean = false, + options: { + related_to?: string, + } = {} +) => (dispatch: Dispatch, getState: GetState) => { + const query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' '); + + if (!query) { + dispatch({ + type: ACTIONS.RESOLVED_SEARCH_FAIL, + }); + return; + } + + const state = getState(); + let queryWithOptions = makeSelectQueryWithOptions(query, size, from, isBackgroundSearch, options)( + state + ); + + // make from null so that we can maintain a reference to the same query for multiple pages and simply append the found results + let queryWithoutFrom = makeSelectQueryWithOptions(query, size, null, isBackgroundSearch, options)( + state + ); + + // If we have already searched for something, we don't need to do anything + // TODO: Tweak this check for multiple page results + /* const resultsForQuery = makeSelectResolvedSearchResults(queryWithOptions)(state); + if (resultsForQuery && resultsForQuery.length && resultsForQuery.length > (from * size)) { + return; + } */ + + dispatch({ + type: ACTIONS.RESOLVED_SEARCH_START, + }); + + if (!state.search.searchQuery && !isBackgroundSearch) { + dispatch(doUpdateSearchQuery(query)); + } + + fetch(`${CONNECTION_STRING}search?resolve=true&${queryWithOptions}`) + .then(handleFetchResponse) + .then((data: Array) => { + const results = []; + + data.forEach(result => { + if (result) { + results.push(result); + } + }); + + dispatch({ + type: ACTIONS.RESOLVED_SEARCH_SUCCESS, + data: { + query: queryWithoutFrom, + results, + pageSize: size, + append: parseInt(from, 10) > parseInt(size, 10) - 1, + }, + }); + }) + .catch(e => { + dispatch({ + type: ACTIONS.RESOLVED_SEARCH_FAIL, + }); + }); +}; + export const doFocusSearchInput = () => (dispatch: Dispatch) => dispatch({ type: ACTIONS.SEARCH_FOCUS, diff --git a/src/redux/reducers/search.js b/src/redux/reducers/search.js index ee0bd8b..27e1013 100644 --- a/src/redux/reducers/search.js +++ b/src/redux/reducers/search.js @@ -18,6 +18,8 @@ const defaultState = { }, suggestions: {}, urisByQuery: {}, + resolvedResultsByQuery: {}, + resolvedResultsByQueryLastPageReached: {}, }; export const searchReducer = handleActions( @@ -41,6 +43,47 @@ export const searchReducer = handleActions( searching: false, }), + [ACTIONS.RESOLVED_SEARCH_START]: (state: SearchState): SearchState => ({ + ...state, + searching: true, + }), + [ACTIONS.RESOLVED_SEARCH_SUCCESS]: ( + state: SearchState, + action: ResolvedSearchSuccess + ): SearchState => { + const resolvedResultsByQuery = Object.assign({}, state.resolvedResultsByQuery); + const resolvedResultsByQueryLastPageReached = Object.assign( + {}, + state.resolvedResultsByQueryLastPageReached + ); + const { append, query, results, pageSize } = action.data; + + if (append) { + // todo: check for duplicates when concatenating? + resolvedResultsByQuery[query] = + resolvedResultsByQuery[query] && resolvedResultsByQuery[query].length + ? resolvedResultsByQuery[query].concat(results) + : results; + } else { + resolvedResultsByQuery[query] = results; + } + + // the returned number of urls is less than the page size, so we're on the last page + resolvedResultsByQueryLastPageReached[query] = results.length < pageSize; + + return { + ...state, + searching: false, + resolvedResultsByQuery, + resolvedResultsByQueryLastPageReached, + }; + }, + + [ACTIONS.RESOLVED_SEARCH_FAIL]: (state: SearchState): SearchState => ({ + ...state, + searching: false, + }), + [ACTIONS.UPDATE_SEARCH_QUERY]: ( state: SearchState, action: UpdateSearchQuery diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index e825188..6adf368 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -1,6 +1,9 @@ // @flow import { normalizeURI, buildURI, parseURI } from 'lbryURI'; -import { selectSearchUrisByQuery } from 'redux/selectors/search'; +import { + selectResolvedSearchResultsByQuery, + selectSearchUrisByQuery, +} from 'redux/selectors/search'; import { selectSupportsByOutpoint } from 'redux/selectors/wallet'; import { createSelector } from 'reselect'; import { isClaimNsfw, createNormalizedClaimSearchKey } from 'util/claim'; @@ -639,3 +642,39 @@ export const selectMyStreamUrlsCount = createSelector( selectMyClaimUrisWithoutChannels, channels => channels.length ); + +export const makeSelectResolvedRecommendedContentForUri = (uri: string, size: number) => + createSelector( + makeSelectClaimForUri(uri), + selectResolvedSearchResultsByQuery, + (claim, resolvedResultsByQuery) => { + const atVanityURI = !uri.includes('#'); + + let recommendedContent; + if (claim) { + // always grab full URL - this can change once search returns canonical + const currentUri = buildURI({ streamClaimId: claim.claim_id, streamName: claim.name }); + + const { title } = claim.value; + + if (!title) { + return; + } + + const searchQuery = getSearchQueryString(title.replace(/\//, ' '), { size }, undefined, { + related_to: claim.claim_id, + }); + + let results = resolvedResultsByQuery[searchQuery]; + if (results) { + results = results.filter( + result => + buildURI({ streamClaimId: result.claimId, streamName: result.name }) !== currentUri + ); + recommendedContent = results; + } + } + + return recommendedContent; + } + ); diff --git a/src/redux/selectors/search.js b/src/redux/selectors/search.js index d556602..48dca04 100644 --- a/src/redux/selectors/search.js +++ b/src/redux/selectors/search.js @@ -44,6 +44,38 @@ export const makeSelectSearchUris = (query: string): ((state: State) => Array byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query] ); +export const selectResolvedSearchResultsByQuery: ( + state: State +) => { [string]: Array } = createSelector( + selectState, + state => state.resolvedResultsByQuery +); + +export const selectResolvedSearchResultsByQueryLastPageReached: ( + state: State +) => { [string]: Array } = createSelector( + selectState, + state => state.resolvedResultsByQueryLastPageReached +); + +export const makeSelectResolvedSearchResults = ( + query: string +): ((state: State) => Array) => + // replace statement below is kind of ugly, and repeated in doSearch action + createSelector( + selectResolvedSearchResultsByQuery, + byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query] + ); + +export const makeSelectResolvedSearchResultsLastPageReached = ( + query: string +): ((state: State) => boolean) => + // replace statement below is kind of ugly, and repeated in doSearch action + createSelector( + selectResolvedSearchResultsByQueryLastPageReached, + byQuery => byQuery[query ? query.replace(/^lbry:\/\//i, '').replace(/\//, ' ') : query] + ); + export const selectSearchBarFocused: boolean = createSelector( selectState, state => state.focused From cda1f431b7463aaa74edff5ee9565ca8e935d607 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 22 Jan 2020 09:28:47 -0500 Subject: [PATCH 20/34] update build --- dist/bundle.es.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index a865e0c..3f58baa 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -15,6 +15,7 @@ const CHANNEL_NEW = 'new'; const PAGE_SIZE = 20; var claim = /*#__PURE__*/Object.freeze({ + __proto__: null, MINIMUM_PUBLISH_BID: MINIMUM_PUBLISH_BID, CHANNEL_ANONYMOUS: CHANNEL_ANONYMOUS, CHANNEL_NEW: CHANNEL_NEW, @@ -277,6 +278,7 @@ const TOGGLE_BLOCK_CHANNEL = 'TOGGLE_BLOCK_CHANNEL'; const USER_STATE_POPULATE = 'USER_STATE_POPULATE'; var action_types = /*#__PURE__*/Object.freeze({ + __proto__: null, WINDOW_FOCUSED: WINDOW_FOCUSED, DAEMON_READY: DAEMON_READY, DAEMON_VERSION_MATCH: DAEMON_VERSION_MATCH, @@ -522,6 +524,7 @@ const OTHER = 'other'; const COPYRIGHT = 'copyright'; var licenses = /*#__PURE__*/Object.freeze({ + __proto__: null, CC_LICENSES: CC_LICENSES, NONE: NONE, PUBLIC_DOMAIN: PUBLIC_DOMAIN, @@ -552,6 +555,7 @@ const HISTORY = 'user_history'; const WALLET = 'wallet'; var pages = /*#__PURE__*/Object.freeze({ + __proto__: null, AUTH: AUTH, BACKUP: BACKUP, CHANNEL: CHANNEL, @@ -601,6 +605,7 @@ const RECEIVE_INTERESTS_NOTIFICATIONS = 'receiveInterestsNotifications'; const RECEIVE_CREATOR_NOTIFICATIONS = 'receiveCreatorNotifications'; var settings = /*#__PURE__*/Object.freeze({ + __proto__: null, CREDIT_REQUIRED_ACKNOWLEDGED: CREDIT_REQUIRED_ACKNOWLEDGED, NEW_USER_ACKNOWLEDGED: NEW_USER_ACKNOWLEDGED, EMAIL_COLLECTION_ACKNOWLEDGED: EMAIL_COLLECTION_ACKNOWLEDGED, @@ -628,6 +633,7 @@ const TITLE = 'title'; const FILENAME = 'filename'; var sort_options = /*#__PURE__*/Object.freeze({ + __proto__: null, DATE_NEW: DATE_NEW, DATE_OLD: DATE_OLD, TITLE: TITLE, @@ -641,6 +647,7 @@ const COMPLETE = 'complete'; const MANUAL = 'manual'; var thumbnail_upload_statuses = /*#__PURE__*/Object.freeze({ + __proto__: null, API_DOWN: API_DOWN, READY: READY, IN_PROGRESS: IN_PROGRESS, @@ -660,6 +667,7 @@ const UPDATE = 'update'; const ABANDON = 'abandon'; var transaction_types = /*#__PURE__*/Object.freeze({ + __proto__: null, ALL: ALL, SPEND: SPEND, RECEIVE: RECEIVE, @@ -676,6 +684,7 @@ const PAGE_SIZE$1 = 50; const LATEST_PAGE_SIZE = 20; var transaction_list = /*#__PURE__*/Object.freeze({ + __proto__: null, PAGE_SIZE: PAGE_SIZE$1, LATEST_PAGE_SIZE: LATEST_PAGE_SIZE }); @@ -684,6 +693,7 @@ const SPEECH_STATUS = 'https://spee.ch/api/config/site/publishing'; const SPEECH_PUBLISH = 'https://spee.ch/api/claim/publish'; var speech_urls = /*#__PURE__*/Object.freeze({ + __proto__: null, SPEECH_STATUS: SPEECH_STATUS, SPEECH_PUBLISH: SPEECH_PUBLISH }); @@ -729,6 +739,7 @@ const WALLET_DIR = 'wallet_dir'; const WALLETS = 'wallets'; var daemon_settings = /*#__PURE__*/Object.freeze({ + __proto__: null, ANNOUNCE_HEAD_AND_SD_ONLY: ANNOUNCE_HEAD_AND_SD_ONLY, API: API, BLOB_DOWNLOAD_TIMEOUT: BLOB_DOWNLOAD_TIMEOUT, @@ -782,6 +793,7 @@ var daemon_settings = /*#__PURE__*/Object.freeze({ const WALLET_SERVERS = LBRYUM_SERVERS; var shared_preferences = /*#__PURE__*/Object.freeze({ + __proto__: null, WALLET_SERVERS: WALLET_SERVERS }); From 968686be689fbaf5ba2033ad0a106907320570b9 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 23 Jan 2020 16:01:27 -0500 Subject: [PATCH 21/34] update build --- dist/bundle.es.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 8d472d8..23581cf 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -1264,18 +1264,6 @@ function buildURI(UrlObj, includeProto = true, protoDefault = 'lbry://') { deprecatedParts = _objectWithoutProperties(UrlObj, ['streamName', 'streamClaimId', 'channelName', 'channelClaimId', 'primaryClaimSequence', 'primaryBidPosition', 'secondaryClaimSequence', 'secondaryBidPosition']); const { claimId, claimName, contentName } = deprecatedParts; - { - if (claimId) { - console.error(__("'claimId' should no longer be used. Use 'streamClaimId' or 'channelClaimId' instead")); - } - if (claimName) { - console.error(__("'claimName' should no longer be used. Use 'streamClaimName' or 'channelClaimName' instead")); - } - if (contentName) { - console.error(__("'contentName' should no longer be used. Use 'streamName' instead")); - } - } - if (!claimName && !channelName && !streamName) { console.error(__("'claimName', 'channelName', and 'streamName' are all empty. One must be present to build a url.")); } From 0a4e0ca33f2df3e51c570ba1c637d459a5bbe0a0 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Tue, 28 Jan 2020 16:45:05 -0500 Subject: [PATCH 22/34] Corrects error messages --- src/redux/actions/comments.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/redux/actions/comments.js b/src/redux/actions/comments.js index 4441651..c31dfd3 100644 --- a/src/redux/actions/comments.js +++ b/src/redux/actions/comments.js @@ -76,7 +76,7 @@ export function doCommentCreate( }); dispatch( doToast({ - message: 'Oops, someone broke comments.', + message: 'Unable to create comment, please try again later.', isError: true, }) ); @@ -105,7 +105,7 @@ export function doCommentHide(comment_id: string) { }); dispatch( doToast({ - message: 'There was an error hiding this comment. Please try again later.', + message: 'Unable to hide this comment, please try again later.', isError: true, }) ); @@ -144,7 +144,7 @@ export function doCommentAbandon(comment_id: string) { }); dispatch( doToast({ - message: 'There was an error hiding this comment. Please try again later.', + message: 'Unable to delete this comment, please try again later.', isError: true, }) ); @@ -177,7 +177,7 @@ export function doCommentUpdate(comment_id: string, comment: string) { dispatch({ type: ACTIONS.COMMENT_UPDATE_FAILED, data: error }); dispatch( doToast({ - message: 'There was an error hiding this comment. Please try again later.', + message: 'Unable to edit this comment, please try again later.', isError: true, }) ); From 50528607e79ce327db3a3868f347a366f27aaaaa Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Tue, 28 Jan 2020 17:20:23 -0500 Subject: [PATCH 23/34] Fixes bug where comments would be incorrectly marked as updated & adds user-friendly messages --- dist/bundle.es.js | 69 ++++++++++++++++++++-------------- src/redux/actions/comments.js | 30 +++++++++++---- src/redux/reducers/comments.js | 5 +-- 3 files changed, 64 insertions(+), 40 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 23581cf..5aeafb0 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -15,7 +15,6 @@ const CHANNEL_NEW = 'new'; const PAGE_SIZE = 20; var claim = /*#__PURE__*/Object.freeze({ - __proto__: null, MINIMUM_PUBLISH_BID: MINIMUM_PUBLISH_BID, CHANNEL_ANONYMOUS: CHANNEL_ANONYMOUS, CHANNEL_NEW: CHANNEL_NEW, @@ -286,8 +285,7 @@ const TOGGLE_BLOCK_CHANNEL = 'TOGGLE_BLOCK_CHANNEL'; // Sync const USER_STATE_POPULATE = 'USER_STATE_POPULATE'; -var action_types = /*#__PURE__*/Object.freeze({ - __proto__: null, +var ACTIONS = /*#__PURE__*/Object.freeze({ WINDOW_FOCUSED: WINDOW_FOCUSED, DAEMON_READY: DAEMON_READY, DAEMON_VERSION_MATCH: DAEMON_VERSION_MATCH, @@ -542,7 +540,6 @@ const OTHER = 'other'; const COPYRIGHT = 'copyright'; var licenses = /*#__PURE__*/Object.freeze({ - __proto__: null, CC_LICENSES: CC_LICENSES, NONE: NONE, PUBLIC_DOMAIN: PUBLIC_DOMAIN, @@ -573,7 +570,6 @@ const HISTORY = 'user_history'; const WALLET = 'wallet'; var pages = /*#__PURE__*/Object.freeze({ - __proto__: null, AUTH: AUTH, BACKUP: BACKUP, CHANNEL: CHANNEL, @@ -623,7 +619,6 @@ const RECEIVE_INTERESTS_NOTIFICATIONS = 'receiveInterestsNotifications'; const RECEIVE_CREATOR_NOTIFICATIONS = 'receiveCreatorNotifications'; var settings = /*#__PURE__*/Object.freeze({ - __proto__: null, CREDIT_REQUIRED_ACKNOWLEDGED: CREDIT_REQUIRED_ACKNOWLEDGED, NEW_USER_ACKNOWLEDGED: NEW_USER_ACKNOWLEDGED, EMAIL_COLLECTION_ACKNOWLEDGED: EMAIL_COLLECTION_ACKNOWLEDGED, @@ -651,7 +646,6 @@ const TITLE = 'title'; const FILENAME = 'filename'; var sort_options = /*#__PURE__*/Object.freeze({ - __proto__: null, DATE_NEW: DATE_NEW, DATE_OLD: DATE_OLD, TITLE: TITLE, @@ -665,7 +659,6 @@ const COMPLETE = 'complete'; const MANUAL = 'manual'; var thumbnail_upload_statuses = /*#__PURE__*/Object.freeze({ - __proto__: null, API_DOWN: API_DOWN, READY: READY, IN_PROGRESS: IN_PROGRESS, @@ -685,7 +678,6 @@ const UPDATE = 'update'; const ABANDON = 'abandon'; var transaction_types = /*#__PURE__*/Object.freeze({ - __proto__: null, ALL: ALL, SPEND: SPEND, RECEIVE: RECEIVE, @@ -702,7 +694,6 @@ const PAGE_SIZE$1 = 50; const LATEST_PAGE_SIZE = 20; var transaction_list = /*#__PURE__*/Object.freeze({ - __proto__: null, PAGE_SIZE: PAGE_SIZE$1, LATEST_PAGE_SIZE: LATEST_PAGE_SIZE }); @@ -711,7 +702,6 @@ const SPEECH_STATUS = 'https://spee.ch/api/config/site/publishing'; const SPEECH_PUBLISH = 'https://spee.ch/api/claim/publish'; var speech_urls = /*#__PURE__*/Object.freeze({ - __proto__: null, SPEECH_STATUS: SPEECH_STATUS, SPEECH_PUBLISH: SPEECH_PUBLISH }); @@ -757,7 +747,6 @@ const WALLET_DIR = 'wallet_dir'; const WALLETS = 'wallets'; var daemon_settings = /*#__PURE__*/Object.freeze({ - __proto__: null, ANNOUNCE_HEAD_AND_SD_ONLY: ANNOUNCE_HEAD_AND_SD_ONLY, API: API, BLOB_DOWNLOAD_TIMEOUT: BLOB_DOWNLOAD_TIMEOUT, @@ -811,7 +800,6 @@ var daemon_settings = /*#__PURE__*/Object.freeze({ const WALLET_SERVERS = LBRYUM_SERVERS; var shared_preferences = /*#__PURE__*/Object.freeze({ - __proto__: null, WALLET_SERVERS: WALLET_SERVERS }); @@ -1264,6 +1252,18 @@ function buildURI(UrlObj, includeProto = true, protoDefault = 'lbry://') { deprecatedParts = _objectWithoutProperties(UrlObj, ['streamName', 'streamClaimId', 'channelName', 'channelClaimId', 'primaryClaimSequence', 'primaryBidPosition', 'secondaryClaimSequence', 'secondaryBidPosition']); const { claimId, claimName, contentName } = deprecatedParts; + { + if (claimId) { + console.error(__("'claimId' should no longer be used. Use 'streamClaimId' or 'channelClaimId' instead")); + } + if (claimName) { + console.error(__("'claimName' should no longer be used. Use 'streamClaimName' or 'channelClaimName' instead")); + } + if (contentName) { + console.error(__("'contentName' should no longer be used. Use 'streamName' instead")); + } + } + if (!claimName && !channelName && !streamName) { console.error(__("'claimName', 'channelName', and 'streamName' are all empty. One must be present to build a url.")); } @@ -4269,7 +4269,7 @@ function doCommentCreate(comment = '', claim_id = '', channel, parent_id) { data: error }); dispatch(doToast({ - message: 'Oops, someone broke comments.', + message: 'Unable to create comment, please try again later.', isError: true })); }); @@ -4294,7 +4294,7 @@ function doCommentHide(comment_id) { data: error }); dispatch(doToast({ - message: 'There was an error hiding this comment. Please try again later.', + message: 'Unable to hide this comment, please try again later.', isError: true })); }); @@ -4329,7 +4329,7 @@ function doCommentAbandon(comment_id) { data: error }); dispatch(doToast({ - message: 'There was an error hiding this comment. Please try again later.', + message: 'Unable to delete this comment, please try again later.', isError: true })); }); @@ -4349,16 +4349,30 @@ function doCommentUpdate(comment_id, comment) { comment_id: comment_id, comment: comment }).then(result => { - dispatch({ - type: COMMENT_UPDATE_COMPLETED, - data: { - comment: result - } - }); + if (result != null) { + dispatch({ + type: COMMENT_UPDATE_COMPLETED, + data: { + comment: result + } + }); + } else { + // the result will return null + dispatch({ + type: undefined + }); + dispatch(doToast({ + message: 'Your channel is still being setup, try again in a few moments.', + isError: true + })); + } }).catch(error => { - dispatch({ type: COMMENT_UPDATE_FAILED, data: error }); + dispatch({ + type: COMMENT_UPDATE_FAILED, + data: error + }); dispatch(doToast({ - message: 'There was an error hiding this comment. Please try again later.', + message: 'Unable to edit this comment, please try again later.', isError: true })); }); @@ -4890,10 +4904,7 @@ const commentReducer = handleActions({ [COMMENT_UPDATE_COMPLETED]: (state, action) => { const { comment } = action.data; const commentById = Object.assign({}, state.commentById); - - if (comment) { - commentById[comment.comment_id] = comment; - } + commentById[comment.comment_id] = comment; return _extends$8({}, state, { commentById, @@ -5913,7 +5924,7 @@ const selectChannelIsBlocked = uri => reselect.createSelector(selectBlockedChann return state.includes(uri); }); -exports.ACTIONS = action_types; +exports.ACTIONS = ACTIONS; exports.CLAIM_VALUES = claim; exports.DAEMON_SETTINGS = daemon_settings; exports.DEFAULT_FOLLOWED_TAGS = DEFAULT_FOLLOWED_TAGS; diff --git a/src/redux/actions/comments.js b/src/redux/actions/comments.js index c31dfd3..4c6f876 100644 --- a/src/redux/actions/comments.js +++ b/src/redux/actions/comments.js @@ -166,15 +166,31 @@ export function doCommentUpdate(comment_id: string, comment: string) { comment: comment, }) .then((result: CommentUpdateResponse) => { - dispatch({ - type: ACTIONS.COMMENT_UPDATE_COMPLETED, - data: { - comment: result, - }, - }); + if (result != null) { + dispatch({ + type: ACTIONS.COMMENT_UPDATE_COMPLETED, + data: { + comment: result, + }, + }); + } else { + // the result will return null + dispatch({ + type: ACTIONS.COMENT_UPDATE_FAILED, + }); + dispatch( + doToast({ + message: 'Your channel is still being setup, try again in a few moments.', + isError: true, + }) + ); + } }) .catch(error => { - dispatch({ type: ACTIONS.COMMENT_UPDATE_FAILED, data: error }); + dispatch({ + type: ACTIONS.COMMENT_UPDATE_FAILED, + data: error, + }); dispatch( doToast({ message: 'Unable to edit this comment, please try again later.', diff --git a/src/redux/reducers/comments.js b/src/redux/reducers/comments.js index 493d225..46d08d8 100644 --- a/src/redux/reducers/comments.js +++ b/src/redux/reducers/comments.js @@ -121,10 +121,7 @@ export const commentReducer = handleActions( [ACTIONS.COMMENT_UPDATE_COMPLETED]: (state: CommentsState, action: any) => { const { comment } = action.data; const commentById = Object.assign({}, state.commentById); - - if (comment) { - commentById[comment.comment_id] = comment; - } + commentById[comment.comment_id] = comment; return { ...state, From 4b4217879cc548bef0765e0ab205c19657f23322 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Tue, 28 Jan 2020 17:34:28 -0500 Subject: [PATCH 24/34] Error for abandon operations as well --- dist/bundle.es.js | 4 ++++ src/redux/actions/comments.js | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 5aeafb0..af58953 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -4322,6 +4322,10 @@ function doCommentAbandon(comment_id) { dispatch({ type: COMMENT_ABANDON_FAILED }); + dispatch(doToast({ + message: 'Your channel is still being setup, try again in a few moments.', + isError: true + })); } }).catch(error => { dispatch({ diff --git a/src/redux/actions/comments.js b/src/redux/actions/comments.js index 4c6f876..5ddd34b 100644 --- a/src/redux/actions/comments.js +++ b/src/redux/actions/comments.js @@ -135,6 +135,12 @@ export function doCommentAbandon(comment_id: string) { dispatch({ type: ACTIONS.COMMENT_ABANDON_FAILED, }); + dispatch( + doToast({ + message: 'Your channel is still being setup, try again in a few moments.', + isError: true, + }) + ); } }) .catch(error => { From e8602bdf5ef03ca909c11420bc8a10d8eaa4ee9f Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 29 Jan 2020 14:07:43 -0500 Subject: [PATCH 25/34] yarn build --- dist/bundle.es.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index af58953..116bb55 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -1252,18 +1252,6 @@ function buildURI(UrlObj, includeProto = true, protoDefault = 'lbry://') { deprecatedParts = _objectWithoutProperties(UrlObj, ['streamName', 'streamClaimId', 'channelName', 'channelClaimId', 'primaryClaimSequence', 'primaryBidPosition', 'secondaryClaimSequence', 'secondaryBidPosition']); const { claimId, claimName, contentName } = deprecatedParts; - { - if (claimId) { - console.error(__("'claimId' should no longer be used. Use 'streamClaimId' or 'channelClaimId' instead")); - } - if (claimName) { - console.error(__("'claimName' should no longer be used. Use 'streamClaimName' or 'channelClaimName' instead")); - } - if (contentName) { - console.error(__("'contentName' should no longer be used. Use 'streamName' instead")); - } - } - if (!claimName && !channelName && !streamName) { console.error(__("'claimName', 'channelName', and 'streamName' are all empty. One must be present to build a url.")); } From b5bbece10db5433cab922a773ae42310f6470a66 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 29 Jan 2020 14:18:15 -0500 Subject: [PATCH 26/34] fix typo --- dist/bundle.es.js | 6 +++--- src/redux/actions/comments.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 116bb55..29c130f 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -285,7 +285,7 @@ const TOGGLE_BLOCK_CHANNEL = 'TOGGLE_BLOCK_CHANNEL'; // Sync const USER_STATE_POPULATE = 'USER_STATE_POPULATE'; -var ACTIONS = /*#__PURE__*/Object.freeze({ +var action_types = /*#__PURE__*/Object.freeze({ WINDOW_FOCUSED: WINDOW_FOCUSED, DAEMON_READY: DAEMON_READY, DAEMON_VERSION_MATCH: DAEMON_VERSION_MATCH, @@ -4351,7 +4351,7 @@ function doCommentUpdate(comment_id, comment) { } else { // the result will return null dispatch({ - type: undefined + type: COMMENT_UPDATE_FAILED }); dispatch(doToast({ message: 'Your channel is still being setup, try again in a few moments.', @@ -5916,7 +5916,7 @@ const selectChannelIsBlocked = uri => reselect.createSelector(selectBlockedChann return state.includes(uri); }); -exports.ACTIONS = ACTIONS; +exports.ACTIONS = action_types; exports.CLAIM_VALUES = claim; exports.DAEMON_SETTINGS = daemon_settings; exports.DEFAULT_FOLLOWED_TAGS = DEFAULT_FOLLOWED_TAGS; diff --git a/src/redux/actions/comments.js b/src/redux/actions/comments.js index 5ddd34b..0bcb8cb 100644 --- a/src/redux/actions/comments.js +++ b/src/redux/actions/comments.js @@ -182,7 +182,7 @@ export function doCommentUpdate(comment_id: string, comment: string) { } else { // the result will return null dispatch({ - type: ACTIONS.COMENT_UPDATE_FAILED, + type: ACTIONS.COMMENT_UPDATE_FAILED, }); dispatch( doToast({ From d8c65c5bd3e9de579e28c4570edc61ac7f8b3282 Mon Sep 17 00:00:00 2001 From: jessop Date: Tue, 28 Jan 2020 16:33:35 -0500 Subject: [PATCH 27/34] support blocking mature recommended results if uri is not mature --- src/redux/selectors/claims.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index 6adf368..8a93eb0 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -499,7 +499,8 @@ export const makeSelectRecommendedContentForUri = (uri: string) => createSelector( makeSelectClaimForUri(uri), selectSearchUrisByQuery, - (claim, searchUrisByQuery) => { + makeSelectClaimIsNsfw(uri), + (claim, searchUrisByQuery, isMature) => { const atVanityURI = !uri.includes('#'); let recommendedContent; @@ -513,9 +514,11 @@ export const makeSelectRecommendedContentForUri = (uri: string) => return; } - const searchQuery = getSearchQueryString(title.replace(/\//, ' '), undefined, undefined, { - related_to: claim.claim_id, - }); + const options = { related_to: claim.claim_id } + if (!isMature) { + options['nsfw'] = false; + } + const searchQuery = getSearchQueryString(title.replace(/\//, ' '), undefined, undefined, options); let searchUris = searchUrisByQuery[searchQuery]; if (searchUris) { From 71e85536dbe397df98a47a3c4b4311760b2e7419 Mon Sep 17 00:00:00 2001 From: jessop Date: Wed, 29 Jan 2020 14:20:59 -0500 Subject: [PATCH 28/34] rebase --- dist/bundle.es.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 29c130f..7df3d24 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -2220,7 +2220,7 @@ claim => { return isClaimNsfw(claim); }); -const makeSelectRecommendedContentForUri = uri => reselect.createSelector(makeSelectClaimForUri(uri), selectSearchUrisByQuery, (claim, searchUrisByQuery) => { +const makeSelectRecommendedContentForUri = uri => reselect.createSelector(makeSelectClaimForUri(uri), selectSearchUrisByQuery, makeSelectClaimIsNsfw(uri), (claim, searchUrisByQuery, isMature) => { const atVanityURI = !uri.includes('#'); let recommendedContent; @@ -2234,9 +2234,11 @@ const makeSelectRecommendedContentForUri = uri => reselect.createSelector(makeSe return; } - const searchQuery = getSearchQueryString(title.replace(/\//, ' '), undefined, undefined, { - related_to: claim.claim_id - }); + const options = { related_to: claim.claim_id }; + if (!isMature) { + options['nsfw'] = false; + } + const searchQuery = getSearchQueryString(title.replace(/\//, ' '), undefined, undefined, options); let searchUris = searchUrisByQuery[searchQuery]; if (searchUris) { From f77bee9cf1456f84128fdb74aaf756ec7fd1b8c8 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 30 Jan 2020 17:13:40 -0500 Subject: [PATCH 29/34] handle repost claims --- dist/bundle.es.js | 255 ++++++++++++++++++---------------- dist/flow-typed/Claim.js | 1 + flow-typed/Claim.js | 1 + src/redux/selectors/claims.js | 18 ++- 4 files changed, 152 insertions(+), 123 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 29c130f..de556f7 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -1934,7 +1934,7 @@ function concatClaims(claimList = [], concatClaimList = []) { return claims; } -// +var _extends$4 = 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$2 = state => state.claims || {}; const selectClaimsById = reselect.createSelector(selectState$2, state => state.byId || {}); @@ -2003,7 +2003,7 @@ const makeSelectClaimForUri = uri => reselect.createSelector(selectClaimsByUri, valid = true; } catch (e) {} - if (valid) { + if (valid && byUri) { const claimId = isChannel ? channelClaimId : streamClaimId; const pendingClaim = pendingById[claimId]; @@ -2011,7 +2011,20 @@ const makeSelectClaimForUri = uri => reselect.createSelector(selectClaimsByUri, return pendingClaim; } - return byUri && byUri[normalizeURI(uri)]; + const claim = byUri[normalizeURI(uri)]; + if (claim === undefined || claim === null) { + // Make sure to return the claim as is so apps can check if it's been resolved before (null) or still needs to be resolved (undefined) + return claim; + } + + const repostedClaim = claim.reposted_claim; + if (repostedClaim) { + return _extends$4({}, repostedClaim, { + repost_channel_url: claim.canonical_url + }); + } else { + return claim; + } } }); @@ -2767,7 +2780,7 @@ function batchActions(...actions) { }; } -var _extends$4 = 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$5 = 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 doResolveUris(uris, returnCachedClaims = false) { return (dispatch, getState) => { @@ -2807,7 +2820,7 @@ function doResolveUris(uris, returnCachedClaims = false) { // https://github.com/facebook/flow/issues/2221 if (uriResolveInfo) { if (uriResolveInfo.error) { - resolveInfo[uri] = _extends$4({}, fallbackResolveInfo); + resolveInfo[uri] = _extends$5({}, fallbackResolveInfo); } else { let result = {}; if (uriResolveInfo.value_type === 'channel') { @@ -3497,7 +3510,7 @@ function doSetFileListSort(page, value) { }; } -var _extends$5 = 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$6 = 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; } @@ -3540,7 +3553,7 @@ const selectPublishFormValues = reselect.createSelector(selectState$5, selectIsS } else { actualLanguage = language || 'en'; } - return _extends$5({}, formValues, { language: actualLanguage }); + return _extends$6({}, formValues, { language: actualLanguage }); }); const makeSelectPublishFormValue = item => reselect.createSelector(selectState$5, state => state[item]); @@ -3595,7 +3608,7 @@ const selectTakeOverAmount = reselect.createSelector(selectState$5, selectMyClai return null; }); -var _extends$6 = 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$7 = 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 doResetThumbnailStatus = () => dispatch => { dispatch({ @@ -3633,7 +3646,7 @@ const doClearPublish = () => dispatch => { const doUpdatePublishForm = publishFormValue => dispatch => dispatch({ type: UPDATE_PUBLISH_FORM, - data: _extends$6({}, publishFormValue) + data: _extends$7({}, publishFormValue) }); const doUploadThumbnail = (filePath, thumbnailBlob, fsAdapter, fs, path) => dispatch => { @@ -4381,7 +4394,7 @@ const doToggleBlockChannel = uri => ({ } }); -var _extends$7 = 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 = {}; const defaultState = { @@ -4484,7 +4497,7 @@ reducers[RESOLVE_URIS_STARTED] = (state, action) => { }; reducers[RESOLVE_URIS_COMPLETED] = (state, action) => { - return _extends$7({}, handleClaimAction(state, action)); + return _extends$8({}, handleClaimAction(state, action)); }; reducers[FETCH_CLAIM_LIST_MINE_STARTED] = state => Object.assign({}, state, { @@ -4657,7 +4670,7 @@ reducers[ABANDON_CLAIM_SUCCEEDED] = (state, action) => { }); }; -reducers[CREATE_CHANNEL_STARTED] = state => _extends$7({}, state, { +reducers[CREATE_CHANNEL_STARTED] = state => _extends$8({}, state, { creatingChannel: true, createChannelError: null }); @@ -4745,7 +4758,7 @@ reducers[CLAIM_SEARCH_COMPLETED] = (state, action) => { delete fetchingClaimSearchByQuery[query]; - return Object.assign({}, state, _extends$7({}, handleClaimAction(state, action), { + return Object.assign({}, state, _extends$8({}, handleClaimAction(state, action), { claimSearchByQuery, claimSearchByQueryLastPageReached, fetchingClaimSearchByQuery @@ -4785,7 +4798,7 @@ const handleActions = (actionMap, defaultState) => (state = defaultState, 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; }; +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$1 = { commentById: {}, // commentId -> Comment @@ -4796,11 +4809,11 @@ const defaultState$1 = { }; const commentReducer = handleActions({ - [COMMENT_CREATE_STARTED]: (state, action) => _extends$8({}, state, { + [COMMENT_CREATE_STARTED]: (state, action) => _extends$9({}, state, { isLoading: true }), - [COMMENT_CREATE_FAILED]: (state, action) => _extends$8({}, state, { + [COMMENT_CREATE_FAILED]: (state, action) => _extends$9({}, state, { isLoading: false }), @@ -4818,14 +4831,14 @@ const commentReducer = handleActions({ newCommentIds.unshift(comment.comment_id); byId[claimId] = newCommentIds; - return _extends$8({}, state, { + return _extends$9({}, state, { commentById, byId, isLoading: false }); }, - [COMMENT_LIST_STARTED]: state => _extends$8({}, state, { isLoading: true }), + [COMMENT_LIST_STARTED]: state => _extends$9({}, state, { isLoading: true }), [COMMENT_LIST_COMPLETED]: (state, action) => { const { comments, claimId, uri } = action.data; @@ -4849,7 +4862,7 @@ const commentReducer = handleActions({ byId[claimId] = commentIds; commentsByUri[uri] = claimId; } - return _extends$8({}, state, { + return _extends$9({}, state, { byId, commentById, commentsByUri, @@ -4857,10 +4870,10 @@ const commentReducer = handleActions({ }); }, - [COMMENT_LIST_FAILED]: (state, action) => _extends$8({}, state, { + [COMMENT_LIST_FAILED]: (state, action) => _extends$9({}, state, { isLoading: false }), - [COMMENT_ABANDON_STARTED]: (state, action) => _extends$8({}, state, { + [COMMENT_ABANDON_STARTED]: (state, action) => _extends$9({}, state, { isLoading: true }), [COMMENT_ABANDON_COMPLETED]: (state, action) => { @@ -4878,18 +4891,18 @@ const commentReducer = handleActions({ } delete commentById[comment_id]; - return _extends$8({}, state, { + return _extends$9({}, state, { commentById, byId, isLoading: false }); }, // do nothing - [COMMENT_ABANDON_FAILED]: (state, action) => _extends$8({}, state, { + [COMMENT_ABANDON_FAILED]: (state, action) => _extends$9({}, state, { isLoading: false }), // do nothing - [COMMENT_UPDATE_STARTED]: (state, action) => _extends$8({}, state, { + [COMMENT_UPDATE_STARTED]: (state, action) => _extends$9({}, state, { isLoading: true }), // replace existing comment with comment returned here under its comment_id @@ -4898,29 +4911,29 @@ const commentReducer = handleActions({ const commentById = Object.assign({}, state.commentById); commentById[comment.comment_id] = comment; - return _extends$8({}, state, { + return _extends$9({}, state, { commentById, isLoading: false }); }, // nothing can be done here - [COMMENT_UPDATE_FAILED]: (state, action) => _extends$8({}, state, { + [COMMENT_UPDATE_FAILED]: (state, action) => _extends$9({}, state, { isLoading: false }), // nothing can really be done here - [COMMENT_HIDE_STARTED]: (state, action) => _extends$8({}, state, { + [COMMENT_HIDE_STARTED]: (state, action) => _extends$9({}, state, { isLoading: true }), - [COMMENT_HIDE_COMPLETED]: (state, action) => _extends$8({}, state, { // todo: add HiddenComments state & create selectors + [COMMENT_HIDE_COMPLETED]: (state, action) => _extends$9({}, state, { // todo: add HiddenComments state & create selectors isLoading: false }), // nothing can be done here - [COMMENT_HIDE_FAILED]: (state, action) => _extends$8({}, state, { + [COMMENT_HIDE_FAILED]: (state, action) => _extends$9({}, state, { isLoading: false }) }, defaultState$1); -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$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; }; const reducers$1 = {}; const defaultState$2 = { @@ -4929,9 +4942,9 @@ const defaultState$2 = { reducers$1[SET_CONTENT_POSITION] = (state, action) => { const { claimId, outpoint, position } = action.data; - return _extends$9({}, state, { - positions: _extends$9({}, state.positions, { - [claimId]: _extends$9({}, state.positions[claimId], { + return _extends$a({}, state, { + positions: _extends$a({}, state.positions, { + [claimId]: _extends$a({}, state.positions[claimId], { [outpoint]: position }) }) @@ -5098,7 +5111,7 @@ function fileInfoReducer(state = defaultState$3, 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$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 reducers$3 = {}; const defaultState$4 = { @@ -5114,7 +5127,7 @@ reducers$3[PURCHASE_URI_STARTED] = (state, action) => { newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1); } - return _extends$a({}, state, { + return _extends$b({}, state, { failedPurchaseUris: newFailedPurchaseUris, purchaseUriErrorMessage: '' }); @@ -5132,7 +5145,7 @@ reducers$3[PURCHASE_URI_COMPLETED] = (state, action) => { newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1); } - return _extends$a({}, state, { + return _extends$b({}, state, { failedPurchaseUris: newFailedPurchaseUris, purchasedUris: newPurchasedUris, purchaseUriErrorMessage: '' @@ -5147,7 +5160,7 @@ reducers$3[PURCHASE_URI_FAILED] = (state, action) => { newFailedPurchaseUris.push(uri); } - return _extends$a({}, state, { + return _extends$b({}, state, { failedPurchaseUris: newFailedPurchaseUris, purchaseUriErrorMessage: error }); @@ -5160,7 +5173,7 @@ reducers$3[DELETE_PURCHASED_URI] = (state, action) => { newPurchasedUris.splice(newPurchasedUris.indexOf(uri), 1); } - return _extends$a({}, state, { + return _extends$b({}, state, { purchasedUris: newPurchasedUris }); }; @@ -5171,7 +5184,7 @@ function fileReducer(state = defaultState$4, action) { return state; } -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$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; }; const defaultState$5 = { notifications: [], @@ -5186,7 +5199,7 @@ const notificationsReducer = handleActions({ const newToasts = state.toasts.slice(); newToasts.push(toast); - return _extends$b({}, state, { + return _extends$c({}, state, { toasts: newToasts }); }, @@ -5194,7 +5207,7 @@ const notificationsReducer = handleActions({ const newToasts = state.toasts.slice(); newToasts.shift(); - return _extends$b({}, state, { + return _extends$c({}, state, { toasts: newToasts }); }, @@ -5205,7 +5218,7 @@ const notificationsReducer = handleActions({ const newNotifications = state.notifications.slice(); newNotifications.push(notification); - return _extends$b({}, state, { + return _extends$c({}, state, { notifications: newNotifications }); }, @@ -5216,7 +5229,7 @@ const notificationsReducer = handleActions({ notifications = notifications.map(pastNotification => pastNotification.id === notification.id ? notification : pastNotification); - return _extends$b({}, state, { + return _extends$c({}, state, { notifications }); }, @@ -5225,7 +5238,7 @@ const notificationsReducer = handleActions({ let newNotifications = state.notifications.slice(); newNotifications = newNotifications.filter(notification => notification.id !== id); - return _extends$b({}, state, { + return _extends$c({}, state, { notifications: newNotifications }); }, @@ -5236,7 +5249,7 @@ const notificationsReducer = handleActions({ const newErrors = state.errors.slice(); newErrors.push(error); - return _extends$b({}, state, { + return _extends$c({}, state, { errors: newErrors }); }, @@ -5244,13 +5257,13 @@ const notificationsReducer = handleActions({ const newErrors = state.errors.slice(); newErrors.shift(); - return _extends$b({}, state, { + return _extends$c({}, state, { errors: newErrors }); } }, defaultState$5); -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$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; }; function _objectWithoutProperties$3(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; } @@ -5287,17 +5300,17 @@ const defaultState$6 = { const publishReducer = handleActions({ [UPDATE_PUBLISH_FORM]: (state, action) => { const { data } = action; - return _extends$c({}, state, data); + return _extends$d({}, state, data); }, - [CLEAR_PUBLISH]: () => _extends$c({}, defaultState$6), - [PUBLISH_START]: state => _extends$c({}, state, { + [CLEAR_PUBLISH]: () => _extends$d({}, defaultState$6), + [PUBLISH_START]: state => _extends$d({}, state, { publishing: true, publishSuccess: false }), - [PUBLISH_FAIL]: state => _extends$c({}, state, { + [PUBLISH_FAIL]: state => _extends$d({}, state, { publishing: false }), - [PUBLISH_SUCCESS]: state => _extends$c({}, state, { + [PUBLISH_SUCCESS]: state => _extends$d({}, state, { publishing: false, publishSuccess: true }), @@ -5312,14 +5325,14 @@ const publishReducer = handleActions({ streamName: name }); - return _extends$c({}, defaultState$6, publishData, { + return _extends$d({}, defaultState$6, publishData, { editingURI: uri, uri: shortUri }); } }, defaultState$6); -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$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 defaultState$7 = { isActive: false, // does the user have any typed text in the search input @@ -5341,23 +5354,23 @@ const defaultState$7 = { }; const searchReducer = handleActions({ - [SEARCH_START]: state => _extends$d({}, state, { + [SEARCH_START]: state => _extends$e({}, state, { searching: true }), [SEARCH_SUCCESS]: (state, action) => { const { query, uris } = action.data; - return _extends$d({}, state, { + return _extends$e({}, state, { searching: false, urisByQuery: Object.assign({}, state.urisByQuery, { [query]: uris }) }); }, - [SEARCH_FAIL]: state => _extends$d({}, state, { + [SEARCH_FAIL]: state => _extends$e({}, state, { searching: false }), - [RESOLVED_SEARCH_START]: state => _extends$d({}, state, { + [RESOLVED_SEARCH_START]: state => _extends$e({}, state, { searching: true }), [RESOLVED_SEARCH_SUCCESS]: (state, action) => { @@ -5375,24 +5388,24 @@ const searchReducer = handleActions({ // the returned number of urls is less than the page size, so we're on the last page resolvedResultsByQueryLastPageReached[query] = results.length < pageSize; - return _extends$d({}, state, { + return _extends$e({}, state, { searching: false, resolvedResultsByQuery, resolvedResultsByQueryLastPageReached }); }, - [RESOLVED_SEARCH_FAIL]: state => _extends$d({}, state, { + [RESOLVED_SEARCH_FAIL]: state => _extends$e({}, state, { searching: false }), - [UPDATE_SEARCH_QUERY]: (state, action) => _extends$d({}, state, { + [UPDATE_SEARCH_QUERY]: (state, action) => _extends$e({}, state, { searchQuery: action.data.query, isActive: true }), - [UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$d({}, state, { - suggestions: _extends$d({}, state.suggestions, { + [UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$e({}, state, { + suggestions: _extends$e({}, state.suggestions, { [action.data.query]: action.data.suggestions }) }), @@ -5400,30 +5413,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$d({}, state, { + [DISMISS_NOTIFICATION]: state => _extends$e({}, state, { isActive: false }), - [SEARCH_FOCUS]: state => _extends$d({}, state, { + [SEARCH_FOCUS]: state => _extends$e({}, state, { focused: true }), - [SEARCH_BLUR]: state => _extends$d({}, state, { + [SEARCH_BLUR]: state => _extends$e({}, state, { focused: false }), [UPDATE_SEARCH_OPTIONS]: (state, action) => { const { options: oldOptions } = state; const newOptions = action.data; - const options = _extends$d({}, oldOptions, newOptions); - return _extends$d({}, state, { + const options = _extends$e({}, oldOptions, newOptions); + return _extends$e({}, state, { options }); } }, defaultState$7); -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$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; }; function getDefaultKnownTags() { - return DEFAULT_FOLLOWED_TAGS.concat(DEFAULT_KNOWN_TAGS).reduce((tagsMap, tag) => _extends$e({}, tagsMap, { + return DEFAULT_FOLLOWED_TAGS.concat(DEFAULT_KNOWN_TAGS).reduce((tagsMap, tag) => _extends$f({}, tagsMap, { [tag]: { name: tag } }), {}); } @@ -5446,7 +5459,7 @@ const tagsReducer = handleActions({ newFollowedTags.push(name); } - return _extends$e({}, state, { + return _extends$f({}, state, { followedTags: newFollowedTags }); }, @@ -5455,10 +5468,10 @@ const tagsReducer = handleActions({ const { knownTags } = state; const { name } = action.data; - let newKnownTags = _extends$e({}, knownTags); + let newKnownTags = _extends$f({}, knownTags); newKnownTags[name] = { name }; - return _extends$e({}, state, { + return _extends$f({}, state, { knownTags: newKnownTags }); }, @@ -5467,24 +5480,24 @@ const tagsReducer = handleActions({ const { knownTags, followedTags } = state; const { name } = action.data; - let newKnownTags = _extends$e({}, knownTags); + let newKnownTags = _extends$f({}, knownTags); delete newKnownTags[name]; const newFollowedTags = followedTags.filter(tag => tag !== name); - return _extends$e({}, state, { + return _extends$f({}, state, { knownTags: newKnownTags, followedTags: newFollowedTags }); }, [USER_STATE_POPULATE]: (state, action) => { const { tags } = action.data; - return _extends$e({}, state, { + return _extends$f({}, state, { followedTags: tags && tags.length ? tags : DEFAULT_FOLLOWED_TAGS }); } }, defaultState$8); -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$g = 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$9 = { blockedChannels: [] @@ -5508,13 +5521,13 @@ const blockedReducer = handleActions({ }, [USER_STATE_POPULATE]: (state, action) => { const { blocked } = action.data; - return _extends$f({}, state, { + return _extends$g({}, state, { blockedChannels: blocked && blocked.length ? blocked : state.blockedChannels }); } }, defaultState$9); -var _extends$g = 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$h = 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, @@ -5559,25 +5572,25 @@ const defaultState$a = { }; const walletReducer = handleActions({ - [FETCH_TRANSACTIONS_STARTED]: state => _extends$g({}, state, { + [FETCH_TRANSACTIONS_STARTED]: state => _extends$h({}, state, { fetchingTransactions: true }), [FETCH_TRANSACTIONS_COMPLETED]: (state, action) => { - const byId = _extends$g({}, state.transactions); + const byId = _extends$h({}, state.transactions); const { transactions } = action.data; transactions.forEach(transaction => { byId[transaction.txid] = transaction; }); - return _extends$g({}, state, { + return _extends$h({}, state, { transactions: byId, fetchingTransactions: false }); }, - [FETCH_SUPPORTS_STARTED]: state => _extends$g({}, state, { + [FETCH_SUPPORTS_STARTED]: state => _extends$h({}, state, { fetchingSupports: true }), @@ -5590,7 +5603,7 @@ const walletReducer = handleActions({ byOutpoint[`${txid}:${nout}`] = transaction; }); - return _extends$g({}, state, { supports: byOutpoint, fetchingSupports: false }); + return _extends$h({}, state, { supports: byOutpoint, fetchingSupports: false }); }, [ABANDON_SUPPORT_STARTED]: (state, action) => { @@ -5599,7 +5612,7 @@ const walletReducer = handleActions({ currentlyAbandoning[outpoint] = true; - return _extends$g({}, state, { + return _extends$h({}, state, { abandoningSupportsByOutpoint: currentlyAbandoning }); }, @@ -5612,23 +5625,23 @@ const walletReducer = handleActions({ delete currentlyAbandoning[outpoint]; delete byOutpoint[outpoint]; - return _extends$g({}, state, { + return _extends$h({}, state, { supports: byOutpoint, abandoningSupportsById: currentlyAbandoning }); }, - [GET_NEW_ADDRESS_STARTED]: state => _extends$g({}, state, { + [GET_NEW_ADDRESS_STARTED]: state => _extends$h({}, state, { gettingNewAddress: true }), [GET_NEW_ADDRESS_COMPLETED]: (state, action) => { const { address } = action.data; - return _extends$g({}, state, { gettingNewAddress: false, receiveAddress: address }); + return _extends$h({}, state, { gettingNewAddress: false, receiveAddress: address }); }, - [UPDATE_BALANCE]: (state, action) => _extends$g({}, state, { + [UPDATE_BALANCE]: (state, action) => _extends$h({}, state, { totalBalance: action.data.totalBalance, balance: action.data.balance, reservedBalance: action.data.reservedBalance, @@ -5637,32 +5650,32 @@ const walletReducer = handleActions({ tipsBalance: action.data.tipsBalance }), - [CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$g({}, state, { + [CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$h({}, state, { checkingAddressOwnership: true }), - [CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$g({}, state, { + [CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$h({}, state, { checkingAddressOwnership: false }), [SET_DRAFT_TRANSACTION_AMOUNT]: (state, action) => { const oldDraft = state.draftTransaction; - const newDraft = _extends$g({}, oldDraft, { amount: parseFloat(action.data.amount) }); + const newDraft = _extends$h({}, oldDraft, { amount: parseFloat(action.data.amount) }); - return _extends$g({}, state, { draftTransaction: newDraft }); + return _extends$h({}, state, { draftTransaction: newDraft }); }, [SET_DRAFT_TRANSACTION_ADDRESS]: (state, action) => { const oldDraft = state.draftTransaction; - const newDraft = _extends$g({}, oldDraft, { address: action.data.address }); + const newDraft = _extends$h({}, oldDraft, { address: action.data.address }); - return _extends$g({}, state, { draftTransaction: newDraft }); + return _extends$h({}, state, { draftTransaction: newDraft }); }, [SEND_TRANSACTION_STARTED]: state => { - const newDraftTransaction = _extends$g({}, state.draftTransaction, { sending: true }); + const newDraftTransaction = _extends$h({}, state.draftTransaction, { sending: true }); - return _extends$g({}, state, { draftTransaction: newDraftTransaction }); + return _extends$h({}, state, { draftTransaction: newDraftTransaction }); }, [SEND_TRANSACTION_COMPLETED]: state => Object.assign({}, state, { @@ -5675,114 +5688,114 @@ const walletReducer = handleActions({ error: action.data.error }); - return _extends$g({}, state, { draftTransaction: newDraftTransaction }); + return _extends$h({}, state, { draftTransaction: newDraftTransaction }); }, - [SUPPORT_TRANSACTION_STARTED]: state => _extends$g({}, state, { + [SUPPORT_TRANSACTION_STARTED]: state => _extends$h({}, state, { sendingSupport: true }), - [SUPPORT_TRANSACTION_COMPLETED]: state => _extends$g({}, state, { + [SUPPORT_TRANSACTION_COMPLETED]: state => _extends$h({}, state, { sendingSupport: false }), - [SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$g({}, state, { + [SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$h({}, state, { error: action.data.error, sendingSupport: false }), - [CLEAR_SUPPORT_TRANSACTION]: state => _extends$g({}, state, { + [CLEAR_SUPPORT_TRANSACTION]: state => _extends$h({}, state, { sendingSupport: false }), - [WALLET_STATUS_COMPLETED]: (state, action) => _extends$g({}, state, { + [WALLET_STATUS_COMPLETED]: (state, action) => _extends$h({}, state, { walletIsEncrypted: action.result }), - [WALLET_ENCRYPT_START]: state => _extends$g({}, state, { + [WALLET_ENCRYPT_START]: state => _extends$h({}, state, { walletEncryptPending: true, walletEncryptSucceded: null, walletEncryptResult: null }), - [WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$g({}, state, { + [WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$h({}, state, { walletEncryptPending: false, walletEncryptSucceded: true, walletEncryptResult: action.result }), - [WALLET_ENCRYPT_FAILED]: (state, action) => _extends$g({}, state, { + [WALLET_ENCRYPT_FAILED]: (state, action) => _extends$h({}, state, { walletEncryptPending: false, walletEncryptSucceded: false, walletEncryptResult: action.result }), - [WALLET_DECRYPT_START]: state => _extends$g({}, state, { + [WALLET_DECRYPT_START]: state => _extends$h({}, state, { walletDecryptPending: true, walletDecryptSucceded: null, walletDecryptResult: null }), - [WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$g({}, state, { + [WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$h({}, state, { walletDecryptPending: false, walletDecryptSucceded: true, walletDecryptResult: action.result }), - [WALLET_DECRYPT_FAILED]: (state, action) => _extends$g({}, state, { + [WALLET_DECRYPT_FAILED]: (state, action) => _extends$h({}, state, { walletDecryptPending: false, walletDecryptSucceded: false, walletDecryptResult: action.result }), - [WALLET_UNLOCK_START]: state => _extends$g({}, state, { + [WALLET_UNLOCK_START]: state => _extends$h({}, state, { walletUnlockPending: true, walletUnlockSucceded: null, walletUnlockResult: null }), - [WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$g({}, state, { + [WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$h({}, state, { walletUnlockPending: false, walletUnlockSucceded: true, walletUnlockResult: action.result }), - [WALLET_UNLOCK_FAILED]: (state, action) => _extends$g({}, state, { + [WALLET_UNLOCK_FAILED]: (state, action) => _extends$h({}, state, { walletUnlockPending: false, walletUnlockSucceded: false, walletUnlockResult: action.result }), - [WALLET_LOCK_START]: state => _extends$g({}, state, { + [WALLET_LOCK_START]: state => _extends$h({}, state, { walletLockPending: false, walletLockSucceded: null, walletLockResult: null }), - [WALLET_LOCK_COMPLETED]: (state, action) => _extends$g({}, state, { + [WALLET_LOCK_COMPLETED]: (state, action) => _extends$h({}, state, { walletLockPending: false, walletLockSucceded: true, walletLockResult: action.result }), - [WALLET_LOCK_FAILED]: (state, action) => _extends$g({}, state, { + [WALLET_LOCK_FAILED]: (state, action) => _extends$h({}, state, { walletLockPending: false, walletLockSucceded: false, walletLockResult: action.result }), - [SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$g({}, state, { + [SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$h({}, state, { transactionListFilter: action.data }), - [UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$g({}, state, { + [UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$h({}, state, { latestBlock: action.data }), - [WALLET_RESTART]: state => _extends$g({}, state, { + [WALLET_RESTART]: state => _extends$h({}, state, { walletReconnecting: true }), - [WALLET_RESTART_COMPLETED]: state => _extends$g({}, state, { + [WALLET_RESTART_COMPLETED]: state => _extends$h({}, state, { walletReconnecting: false }) }, defaultState$a); @@ -5800,14 +5813,14 @@ const makeSelectContentPositionForUri = uri => reselect.createSelector(selectSta return state.positions[id] ? state.positions[id][outpoint] : null; }); -var _extends$h = 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$i = 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$h({ + return _extends$i({ id }, params); } diff --git a/dist/flow-typed/Claim.js b/dist/flow-typed/Claim.js index 54e414f..5ebe5e9 100644 --- a/dist/flow-typed/Claim.js +++ b/dist/flow-typed/Claim.js @@ -33,6 +33,7 @@ declare type GenericClaim = { type: 'claim' | 'update' | 'support', value_type: 'stream' | 'channel', signing_channel?: ChannelClaim, + repost_channel_url?: string, meta: { activation_height: number, claims_in_channel?: number, diff --git a/flow-typed/Claim.js b/flow-typed/Claim.js index 54e414f..5ebe5e9 100644 --- a/flow-typed/Claim.js +++ b/flow-typed/Claim.js @@ -33,6 +33,7 @@ declare type GenericClaim = { type: 'claim' | 'update' | 'support', value_type: 'stream' | 'channel', signing_channel?: ChannelClaim, + repost_channel_url?: string, meta: { activation_height: number, claims_in_channel?: number, diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index 6adf368..900f8d7 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -114,7 +114,7 @@ export const makeSelectClaimForUri = (uri: string) => valid = true; } catch (e) {} - if (valid) { + if (valid && byUri) { const claimId = isChannel ? channelClaimId : streamClaimId; const pendingClaim = pendingById[claimId]; @@ -122,7 +122,21 @@ export const makeSelectClaimForUri = (uri: string) => return pendingClaim; } - return byUri && byUri[normalizeURI(uri)]; + const claim = byUri[normalizeURI(uri)]; + if (claim === undefined || claim === null) { + // Make sure to return the claim as is so apps can check if it's been resolved before (null) or still needs to be resolved (undefined) + return claim; + } + + const repostedClaim = claim.reposted_claim; + if (repostedClaim) { + return { + ...repostedClaim, + repost_channel_url: claim.canonical_url, + }; + } else { + return claim; + } } } ); From bfbaa0dbdd2c1b2b340c0760d0d97c99f3cefb02 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 30 Jan 2020 17:44:08 -0500 Subject: [PATCH 30/34] fix typo --- dist/bundle.es.js | 4 +++- src/redux/selectors/claims.js | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 523d972..f029ce8 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -2019,8 +2019,10 @@ const makeSelectClaimForUri = uri => reselect.createSelector(selectClaimsByUri, const repostedClaim = claim.reposted_claim; if (repostedClaim) { + const channelUrl = claim.signing_channel && claim.signing_channel.canonical_url; + return _extends$4({}, repostedClaim, { - repost_channel_url: claim.canonical_url + repost_channel_url: channelUrl }); } else { return claim; diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index 51e5e33..cc8aff6 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -130,9 +130,11 @@ export const makeSelectClaimForUri = (uri: string) => const repostedClaim = claim.reposted_claim; if (repostedClaim) { + const channelUrl = claim.signing_channel && claim.signing_channel.canonical_url; + return { ...repostedClaim, - repost_channel_url: claim.canonical_url, + repost_channel_url: channelUrl, }; } else { return claim; @@ -277,8 +279,8 @@ export const makeSelectDateForUri = (uri: string) => (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta && claim.meta.creation_timestamp - ? claim.meta.creation_timestamp * 1000 - : null); + ? claim.meta.creation_timestamp * 1000 + : null); if (!timestamp) { return undefined; } @@ -528,11 +530,16 @@ export const makeSelectRecommendedContentForUri = (uri: string) => return; } - const options = { related_to: claim.claim_id } + const options = { related_to: claim.claim_id }; if (!isMature) { options['nsfw'] = false; } - const searchQuery = getSearchQueryString(title.replace(/\//, ' '), undefined, undefined, options); + const searchQuery = getSearchQueryString( + title.replace(/\//, ' '), + undefined, + undefined, + options + ); let searchUris = searchUrisByQuery[searchQuery]; if (searchUris) { From 635381a616da9da31bba33637ca0dcaaf9692053 Mon Sep 17 00:00:00 2001 From: jessop Date: Thu, 30 Jan 2020 01:30:27 -0500 Subject: [PATCH 31/34] convert search options to expandable object wip bundle --- dist/bundle.es.js | 63 ++++++++++++++++++++++++----------- src/redux/actions/search.js | 51 +++++++++++++++++++++------- src/redux/selectors/claims.js | 21 ++++++------ src/redux/selectors/search.js | 25 +++++++------- src/util/query-params.js | 10 ++++-- 5 files changed, 114 insertions(+), 56 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index f029ce8..d619f34 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -1071,9 +1071,11 @@ function toQueryString(params) { return parts.join('&'); } -const getSearchQueryString = (query, options = {}, includeUserOptions = false, additionalOptions = {}) => { +const getSearchQueryString = (query, options = {}) => { const encodedQuery = encodeURIComponent(query); const queryParams = [`s=${encodedQuery}`, `size=${options.size || DEFAULT_SEARCH_SIZE}`, `from=${options.from || DEFAULT_SEARCH_RESULT_FROM}`]; + const { isBackgroundSearch } = options; + const includeUserOptions = typeof isBackgroundSearch === 'undefined' ? false : !isBackgroundSearch; if (includeUserOptions) { const claimType = options[SEARCH_OPTIONS.CLAIM_TYPE]; @@ -1085,6 +1087,12 @@ const getSearchQueryString = (query, options = {}, includeUserOptions = false, a } } + const additionalOptions = {}; + const { related_to } = options; + const { nsfw } = options; + if (related_to) additionalOptions['related_to'] = related_to; + if (typeof nsfw !== 'undefined') additionalOptions['nsfw'] = nsfw; + if (additionalOptions) { Object.keys(additionalOptions).forEach(key => { const option = additionalOptions[key]; @@ -1443,11 +1451,11 @@ const selectSearchSuggestions = reselect.createSelector(selectSearchValue, selec // Creates a query string based on the state in the search reducer // Can be overrided by passing in custom sizes/from values for other areas pagination -const makeSelectQueryWithOptions = (customQuery, customSize, customFrom, isBackgroundSearch = false, // If it's a background search, don't use the users settings -additionalOptions = {}) => reselect.createSelector(selectSearchValue, selectSearchOptions, (query, options) => { - const size = customSize || options[SEARCH_OPTIONS.RESULT_COUNT]; - const queryString = getSearchQueryString(customQuery || query, _extends$1({}, options, { size, from: customFrom }), !isBackgroundSearch, additionalOptions); + +const makeSelectQueryWithOptions = (customQuery, options) => reselect.createSelector(selectSearchValue, selectSearchOptions, (query, defaultOptions) => { + const searchOptions = _extends$1({}, defaultOptions, options); + const queryString = getSearchQueryString(customQuery || query, searchOptions); return queryString; }); @@ -2249,11 +2257,11 @@ const makeSelectRecommendedContentForUri = uri => reselect.createSelector(makeSe return; } - const options = { related_to: claim.claim_id }; + const options = { related_to: claim.claim_id, isBackgroundSearch: true }; if (!isMature) { options['nsfw'] = false; } - const searchQuery = getSearchQueryString(title.replace(/\//, ' '), undefined, undefined, options); + const searchQuery = getSearchQueryString(title.replace(/\//, ' '), options); let searchUris = searchUrisByQuery[searchQuery]; if (searchUris) { @@ -2326,7 +2334,7 @@ const makeSelectMyStreamUrlsForPage = (page = 1) => reselect.createSelector(sele const selectMyStreamUrlsCount = reselect.createSelector(selectMyClaimUrisWithoutChannels, channels => channels.length); -const makeSelectResolvedRecommendedContentForUri = (uri, size) => reselect.createSelector(makeSelectClaimForUri(uri), selectResolvedSearchResultsByQuery, (claim, resolvedResultsByQuery) => { +const makeSelectResolvedRecommendedContentForUri = (uri, size) => reselect.createSelector(makeSelectClaimForUri(uri), selectResolvedSearchResultsByQuery, makeSelectClaimIsNsfw(uri), (claim, resolvedResultsByQuery, isMature) => { const atVanityURI = !uri.includes('#'); let recommendedContent; @@ -2340,9 +2348,12 @@ const makeSelectResolvedRecommendedContentForUri = (uri, size) => reselect.creat return; } - const searchQuery = getSearchQueryString(title.replace(/\//, ' '), { size }, undefined, { - related_to: claim.claim_id - }); + const options = { related_to: claim.claim_id, isBackgroundSearch: true }; + if (!isMature) { + options['nsfw'] = false; + } + + const searchQuery = getSearchQueryString(title.replace(/\//, ' '), options); let results = resolvedResultsByQuery[searchQuery]; if (results) { @@ -3968,7 +3979,7 @@ function handleFetchResponse(response) { return response.status === 200 ? Promise.resolve(response.json()) : Promise.reject(new Error(response.statusText)); } -// +var _extends$7 = 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 DEBOUNCED_SEARCH_SUGGESTION_MS = 300; @@ -4025,9 +4036,10 @@ const doUpdateSearchQuery = (query, shouldSkipSuggestions) => dispatch => { } }; -const doSearch = (rawQuery, size, // only pass in if you don't want to use the users setting (ex: related content) -from, isBackgroundSearch = false, options = {}, resolveResults = true) => (dispatch, getState) => { +const doSearch = (rawQuery, searchOptions) => (dispatch, getState) => { const query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' '); + const resolveResults = searchOptions && searchOptions.resolveResults; + const isBackgroundSearch = searchOptions && searchOptions.isBackgroundSearch || false; if (!query) { dispatch({ @@ -4037,7 +4049,8 @@ from, isBackgroundSearch = false, options = {}, resolveResults = true) => (dispa } const state = getState(); - let queryWithOptions = makeSelectQueryWithOptions(query, size, from, isBackgroundSearch, options)(state); + + let queryWithOptions = makeSelectQueryWithOptions(query, searchOptions)(state); // If we have already searched for something, we don't need to do anything const urisForQuery = makeSelectSearchUris(queryWithOptions)(state); @@ -4108,11 +4121,23 @@ from, isBackgroundSearch = false, options = {}) => (dispatch, getState) => { return; } + const optionsWithFrom = _extends$7({ + size, + from, + isBackgroundSearch + }, options); + + const optionsWithoutFrom = _extends$7({ + size, + isBackgroundSearch + }, options); + const state = getState(); - let queryWithOptions = makeSelectQueryWithOptions(query, size, from, isBackgroundSearch, options)(state); + + let queryWithOptions = makeSelectQueryWithOptions(query, optionsWithFrom)(state); // make from null so that we can maintain a reference to the same query for multiple pages and simply append the found results - let queryWithoutFrom = makeSelectQueryWithOptions(query, size, null, isBackgroundSearch, options)(state); + let queryWithoutFrom = makeSelectQueryWithOptions(query, optionsWithoutFrom)(state); // If we have already searched for something, we don't need to do anything // TODO: Tweak this check for multiple page results @@ -4162,7 +4187,7 @@ const doBlurSearchInput = () => dispatch => dispatch({ type: SEARCH_BLUR }); -const doUpdateSearchOptions = newOptions => (dispatch, getState) => { +const doUpdateSearchOptions = (newOptions, additionalOptions) => (dispatch, getState) => { const state = getState(); const searchValue = selectSearchValue(state); @@ -4173,7 +4198,7 @@ const doUpdateSearchOptions = newOptions => (dispatch, getState) => { if (searchValue) { // After updating, perform a search with the new options - dispatch(doSearch(searchValue)); + dispatch(doSearch(searchValue, additionalOptions)); } }; diff --git a/src/redux/actions/search.js b/src/redux/actions/search.js index e00d7ba..9701929 100644 --- a/src/redux/actions/search.js +++ b/src/redux/actions/search.js @@ -17,6 +17,20 @@ const DEBOUNCED_SEARCH_SUGGESTION_MS = 300; type Dispatch = (action: any) => any; type GetState = () => { search: SearchState }; +type SearchOptions = { + size?: number, + from?: number, + related_to?: string, + nsfw?: boolean, + isBackgroundSearch?: boolean, + resolveResults?: boolean, +} + +type AdditionalOptions = { + isBackgroundSearch: boolean, + nsfw?: boolean, +} + // We can't use env's because they aren't passed into node_modules let CONNECTION_STRING = 'https://lighthouse.lbry.com/'; @@ -75,17 +89,14 @@ export const doUpdateSearchQuery = (query: string, shouldSkipSuggestions: ?boole } }; + export const doSearch = ( rawQuery: string, - size: ?number, // only pass in if you don't want to use the users setting (ex: related content) - from: ?number, - isBackgroundSearch: boolean = false, - options: { - related_to?: string, - } = {}, - resolveResults: boolean = true + searchOptions: SearchOptions, ) => (dispatch: Dispatch, getState: GetState) => { const query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' '); + const resolveResults = searchOptions && searchOptions.resolveResults; + const isBackgroundSearch = (searchOptions && searchOptions.isBackgroundSearch) || false; if (!query) { dispatch({ @@ -95,7 +106,8 @@ export const doSearch = ( } const state = getState(); - let queryWithOptions = makeSelectQueryWithOptions(query, size, from, isBackgroundSearch, options)( + + let queryWithOptions = makeSelectQueryWithOptions(query, searchOptions)( state ); @@ -167,6 +179,7 @@ export const doResolvedSearch = ( isBackgroundSearch: boolean = false, options: { related_to?: string, + // nsfw here } = {} ) => (dispatch: Dispatch, getState: GetState) => { const query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' '); @@ -178,13 +191,27 @@ export const doResolvedSearch = ( return; } + const optionsWithFrom: SearchOptions = { + size, + from, + isBackgroundSearch, + ...options, + } + + const optionsWithoutFrom: SearchOptions = { + size, + isBackgroundSearch, + ...options, + } + const state = getState(); - let queryWithOptions = makeSelectQueryWithOptions(query, size, from, isBackgroundSearch, options)( + + let queryWithOptions = makeSelectQueryWithOptions(query, optionsWithFrom)( state ); // make from null so that we can maintain a reference to the same query for multiple pages and simply append the found results - let queryWithoutFrom = makeSelectQueryWithOptions(query, size, null, isBackgroundSearch, options)( + let queryWithoutFrom = makeSelectQueryWithOptions(query, optionsWithoutFrom)( state ); @@ -241,7 +268,7 @@ export const doBlurSearchInput = () => (dispatch: Dispatch) => type: ACTIONS.SEARCH_BLUR, }); -export const doUpdateSearchOptions = (newOptions: SearchOptions) => ( +export const doUpdateSearchOptions = (newOptions: SearchOptions, additionalOptions: AdditionalOptions) => ( dispatch: Dispatch, getState: GetState ) => { @@ -255,6 +282,6 @@ export const doUpdateSearchOptions = (newOptions: SearchOptions) => ( if (searchValue) { // After updating, perform a search with the new options - dispatch(doSearch(searchValue)); + dispatch(doSearch(searchValue, additionalOptions)); } }; diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index cc8aff6..c7f489b 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -530,16 +530,11 @@ export const makeSelectRecommendedContentForUri = (uri: string) => return; } - const options = { related_to: claim.claim_id }; + const options = { related_to: claim.claim_id, isBackgroundSearch: true }; if (!isMature) { options['nsfw'] = false; } - const searchQuery = getSearchQueryString( - title.replace(/\//, ' '), - undefined, - undefined, - options - ); + const searchQuery = getSearchQueryString(title.replace(/\//, ' '), options); let searchUris = searchUrisByQuery[searchQuery]; if (searchUris) { @@ -671,7 +666,8 @@ export const makeSelectResolvedRecommendedContentForUri = (uri: string, size: nu createSelector( makeSelectClaimForUri(uri), selectResolvedSearchResultsByQuery, - (claim, resolvedResultsByQuery) => { + makeSelectClaimIsNsfw(uri), + (claim, resolvedResultsByQuery, isMature) => { const atVanityURI = !uri.includes('#'); let recommendedContent; @@ -685,9 +681,12 @@ export const makeSelectResolvedRecommendedContentForUri = (uri: string, size: nu return; } - const searchQuery = getSearchQueryString(title.replace(/\//, ' '), { size }, undefined, { - related_to: claim.claim_id, - }); + const options = { related_to: claim.claim_id, isBackgroundSearch: true } + if (!isMature) { + options['nsfw'] = false; + } + + const searchQuery = getSearchQueryString(title.replace(/\//, ' '), options); let results = resolvedResultsByQuery[searchQuery]; if (results) { diff --git a/src/redux/selectors/search.js b/src/redux/selectors/search.js index 48dca04..e3efd11 100644 --- a/src/redux/selectors/search.js +++ b/src/redux/selectors/search.js @@ -165,26 +165,27 @@ export const selectSearchSuggestions: Array = createSelector( // Creates a query string based on the state in the search reducer // Can be overrided by passing in custom sizes/from values for other areas pagination + +type CustomOptions = { + isBackgroundSearch?: boolean, + size?: number, + from?: number, + related_to?: string, + nsfw?: boolean, +} + export const makeSelectQueryWithOptions = ( customQuery: ?string, - customSize: ?number, - customFrom: ?number, - isBackgroundSearch: boolean = false, // If it's a background search, don't use the users settings - additionalOptions: { - related_to?: string, - } = {} + options: CustomOptions, ) => createSelector( selectSearchValue, selectSearchOptions, - (query, options) => { - const size = customSize || options[SEARCH_OPTIONS.RESULT_COUNT]; - + (query, defaultOptions) => { + const searchOptions = { ...defaultOptions, ...options }; const queryString = getSearchQueryString( customQuery || query, - { ...options, size, from: customFrom }, - !isBackgroundSearch, - additionalOptions + searchOptions, ); return queryString; diff --git a/src/util/query-params.js b/src/util/query-params.js index 7a3da29..80a1d54 100644 --- a/src/util/query-params.js +++ b/src/util/query-params.js @@ -36,8 +36,6 @@ export function toQueryString(params: { [string]: string | number }) { export const getSearchQueryString = ( query: string, options: any = {}, - includeUserOptions: boolean = false, - additionalOptions: {} = {} ) => { const encodedQuery = encodeURIComponent(query); const queryParams = [ @@ -45,6 +43,8 @@ export const getSearchQueryString = ( `size=${options.size || DEFAULT_SEARCH_SIZE}`, `from=${options.from || DEFAULT_SEARCH_RESULT_FROM}`, ]; + const { isBackgroundSearch } = options; + const includeUserOptions = typeof isBackgroundSearch === 'undefined' ? false : !isBackgroundSearch; if (includeUserOptions) { const claimType = options[SEARCH_OPTIONS.CLAIM_TYPE]; @@ -68,6 +68,12 @@ export const getSearchQueryString = ( } } + const additionalOptions = {} + const { related_to } = options; + const { nsfw } = options; + if (related_to) additionalOptions['related_to'] = related_to; + if (typeof nsfw !== 'undefined') additionalOptions['nsfw'] = nsfw; + if (additionalOptions) { Object.keys(additionalOptions).forEach(key => { const option = additionalOptions[key]; From 2b01ce4e79be9e2de11223a4065994567cfc6324 Mon Sep 17 00:00:00 2001 From: jessop Date: Thu, 30 Jan 2020 18:01:27 -0500 Subject: [PATCH 32/34] fix flow errors --- dist/bundle.es.js | 231 +++++++++++++++++----------------- src/redux/actions/search.js | 46 +++---- src/redux/selectors/claims.js | 17 ++- 3 files changed, 146 insertions(+), 148 deletions(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index d619f34..07d9eea 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -2258,6 +2258,7 @@ const makeSelectRecommendedContentForUri = uri => reselect.createSelector(makeSe } const options = { related_to: claim.claim_id, isBackgroundSearch: true }; + if (!isMature) { options['nsfw'] = false; } @@ -3979,7 +3980,7 @@ function handleFetchResponse(response) { return response.status === 200 ? Promise.resolve(response.json()) : Promise.reject(new Error(response.statusText)); } -var _extends$7 = 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 DEBOUNCED_SEARCH_SUGGESTION_MS = 300; @@ -4121,13 +4122,13 @@ from, isBackgroundSearch = false, options = {}) => (dispatch, getState) => { return; } - const optionsWithFrom = _extends$7({ + const optionsWithFrom = _extends$8({ size, from, isBackgroundSearch }, options); - const optionsWithoutFrom = _extends$7({ + const optionsWithoutFrom = _extends$8({ size, isBackgroundSearch }, options); @@ -4423,7 +4424,7 @@ const doToggleBlockChannel = uri => ({ } }); -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; }; +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 reducers = {}; const defaultState = { @@ -4526,7 +4527,7 @@ reducers[RESOLVE_URIS_STARTED] = (state, action) => { }; reducers[RESOLVE_URIS_COMPLETED] = (state, action) => { - return _extends$8({}, handleClaimAction(state, action)); + return _extends$9({}, handleClaimAction(state, action)); }; reducers[FETCH_CLAIM_LIST_MINE_STARTED] = state => Object.assign({}, state, { @@ -4699,7 +4700,7 @@ reducers[ABANDON_CLAIM_SUCCEEDED] = (state, action) => { }); }; -reducers[CREATE_CHANNEL_STARTED] = state => _extends$8({}, state, { +reducers[CREATE_CHANNEL_STARTED] = state => _extends$9({}, state, { creatingChannel: true, createChannelError: null }); @@ -4787,7 +4788,7 @@ reducers[CLAIM_SEARCH_COMPLETED] = (state, action) => { delete fetchingClaimSearchByQuery[query]; - return Object.assign({}, state, _extends$8({}, handleClaimAction(state, action), { + return Object.assign({}, state, _extends$9({}, handleClaimAction(state, action), { claimSearchByQuery, claimSearchByQueryLastPageReached, fetchingClaimSearchByQuery @@ -4827,7 +4828,7 @@ const handleActions = (actionMap, defaultState) => (state = defaultState, 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$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; }; const defaultState$1 = { commentById: {}, // commentId -> Comment @@ -4838,11 +4839,11 @@ const defaultState$1 = { }; const commentReducer = handleActions({ - [COMMENT_CREATE_STARTED]: (state, action) => _extends$9({}, state, { + [COMMENT_CREATE_STARTED]: (state, action) => _extends$a({}, state, { isLoading: true }), - [COMMENT_CREATE_FAILED]: (state, action) => _extends$9({}, state, { + [COMMENT_CREATE_FAILED]: (state, action) => _extends$a({}, state, { isLoading: false }), @@ -4860,14 +4861,14 @@ const commentReducer = handleActions({ newCommentIds.unshift(comment.comment_id); byId[claimId] = newCommentIds; - return _extends$9({}, state, { + return _extends$a({}, state, { commentById, byId, isLoading: false }); }, - [COMMENT_LIST_STARTED]: state => _extends$9({}, state, { isLoading: true }), + [COMMENT_LIST_STARTED]: state => _extends$a({}, state, { isLoading: true }), [COMMENT_LIST_COMPLETED]: (state, action) => { const { comments, claimId, uri } = action.data; @@ -4891,7 +4892,7 @@ const commentReducer = handleActions({ byId[claimId] = commentIds; commentsByUri[uri] = claimId; } - return _extends$9({}, state, { + return _extends$a({}, state, { byId, commentById, commentsByUri, @@ -4899,10 +4900,10 @@ const commentReducer = handleActions({ }); }, - [COMMENT_LIST_FAILED]: (state, action) => _extends$9({}, state, { + [COMMENT_LIST_FAILED]: (state, action) => _extends$a({}, state, { isLoading: false }), - [COMMENT_ABANDON_STARTED]: (state, action) => _extends$9({}, state, { + [COMMENT_ABANDON_STARTED]: (state, action) => _extends$a({}, state, { isLoading: true }), [COMMENT_ABANDON_COMPLETED]: (state, action) => { @@ -4920,18 +4921,18 @@ const commentReducer = handleActions({ } delete commentById[comment_id]; - return _extends$9({}, state, { + return _extends$a({}, state, { commentById, byId, isLoading: false }); }, // do nothing - [COMMENT_ABANDON_FAILED]: (state, action) => _extends$9({}, state, { + [COMMENT_ABANDON_FAILED]: (state, action) => _extends$a({}, state, { isLoading: false }), // do nothing - [COMMENT_UPDATE_STARTED]: (state, action) => _extends$9({}, state, { + [COMMENT_UPDATE_STARTED]: (state, action) => _extends$a({}, state, { isLoading: true }), // replace existing comment with comment returned here under its comment_id @@ -4940,29 +4941,29 @@ const commentReducer = handleActions({ const commentById = Object.assign({}, state.commentById); commentById[comment.comment_id] = comment; - return _extends$9({}, state, { + return _extends$a({}, state, { commentById, isLoading: false }); }, // nothing can be done here - [COMMENT_UPDATE_FAILED]: (state, action) => _extends$9({}, state, { + [COMMENT_UPDATE_FAILED]: (state, action) => _extends$a({}, state, { isLoading: false }), // nothing can really be done here - [COMMENT_HIDE_STARTED]: (state, action) => _extends$9({}, state, { + [COMMENT_HIDE_STARTED]: (state, action) => _extends$a({}, state, { isLoading: true }), - [COMMENT_HIDE_COMPLETED]: (state, action) => _extends$9({}, state, { // todo: add HiddenComments state & create selectors + [COMMENT_HIDE_COMPLETED]: (state, action) => _extends$a({}, state, { // todo: add HiddenComments state & create selectors isLoading: false }), // nothing can be done here - [COMMENT_HIDE_FAILED]: (state, action) => _extends$9({}, state, { + [COMMENT_HIDE_FAILED]: (state, action) => _extends$a({}, state, { isLoading: false }) }, defaultState$1); -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$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 reducers$1 = {}; const defaultState$2 = { @@ -4971,9 +4972,9 @@ const defaultState$2 = { reducers$1[SET_CONTENT_POSITION] = (state, action) => { const { claimId, outpoint, position } = action.data; - return _extends$a({}, state, { - positions: _extends$a({}, state.positions, { - [claimId]: _extends$a({}, state.positions[claimId], { + return _extends$b({}, state, { + positions: _extends$b({}, state.positions, { + [claimId]: _extends$b({}, state.positions[claimId], { [outpoint]: position }) }) @@ -5140,7 +5141,7 @@ function fileInfoReducer(state = defaultState$3, action) { return state; } -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$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; }; const reducers$3 = {}; const defaultState$4 = { @@ -5156,7 +5157,7 @@ reducers$3[PURCHASE_URI_STARTED] = (state, action) => { newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1); } - return _extends$b({}, state, { + return _extends$c({}, state, { failedPurchaseUris: newFailedPurchaseUris, purchaseUriErrorMessage: '' }); @@ -5174,7 +5175,7 @@ reducers$3[PURCHASE_URI_COMPLETED] = (state, action) => { newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1); } - return _extends$b({}, state, { + return _extends$c({}, state, { failedPurchaseUris: newFailedPurchaseUris, purchasedUris: newPurchasedUris, purchaseUriErrorMessage: '' @@ -5189,7 +5190,7 @@ reducers$3[PURCHASE_URI_FAILED] = (state, action) => { newFailedPurchaseUris.push(uri); } - return _extends$b({}, state, { + return _extends$c({}, state, { failedPurchaseUris: newFailedPurchaseUris, purchaseUriErrorMessage: error }); @@ -5202,7 +5203,7 @@ reducers$3[DELETE_PURCHASED_URI] = (state, action) => { newPurchasedUris.splice(newPurchasedUris.indexOf(uri), 1); } - return _extends$b({}, state, { + return _extends$c({}, state, { purchasedUris: newPurchasedUris }); }; @@ -5213,7 +5214,7 @@ function fileReducer(state = defaultState$4, action) { return state; } -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$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 defaultState$5 = { notifications: [], @@ -5228,7 +5229,7 @@ const notificationsReducer = handleActions({ const newToasts = state.toasts.slice(); newToasts.push(toast); - return _extends$c({}, state, { + return _extends$d({}, state, { toasts: newToasts }); }, @@ -5236,7 +5237,7 @@ const notificationsReducer = handleActions({ const newToasts = state.toasts.slice(); newToasts.shift(); - return _extends$c({}, state, { + return _extends$d({}, state, { toasts: newToasts }); }, @@ -5247,7 +5248,7 @@ const notificationsReducer = handleActions({ const newNotifications = state.notifications.slice(); newNotifications.push(notification); - return _extends$c({}, state, { + return _extends$d({}, state, { notifications: newNotifications }); }, @@ -5258,7 +5259,7 @@ const notificationsReducer = handleActions({ notifications = notifications.map(pastNotification => pastNotification.id === notification.id ? notification : pastNotification); - return _extends$c({}, state, { + return _extends$d({}, state, { notifications }); }, @@ -5267,7 +5268,7 @@ const notificationsReducer = handleActions({ let newNotifications = state.notifications.slice(); newNotifications = newNotifications.filter(notification => notification.id !== id); - return _extends$c({}, state, { + return _extends$d({}, state, { notifications: newNotifications }); }, @@ -5278,7 +5279,7 @@ const notificationsReducer = handleActions({ const newErrors = state.errors.slice(); newErrors.push(error); - return _extends$c({}, state, { + return _extends$d({}, state, { errors: newErrors }); }, @@ -5286,13 +5287,13 @@ const notificationsReducer = handleActions({ const newErrors = state.errors.slice(); newErrors.shift(); - return _extends$c({}, state, { + return _extends$d({}, state, { errors: newErrors }); } }, defaultState$5); -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$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; }; function _objectWithoutProperties$3(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; } @@ -5329,17 +5330,17 @@ const defaultState$6 = { const publishReducer = handleActions({ [UPDATE_PUBLISH_FORM]: (state, action) => { const { data } = action; - return _extends$d({}, state, data); + return _extends$e({}, state, data); }, - [CLEAR_PUBLISH]: () => _extends$d({}, defaultState$6), - [PUBLISH_START]: state => _extends$d({}, state, { + [CLEAR_PUBLISH]: () => _extends$e({}, defaultState$6), + [PUBLISH_START]: state => _extends$e({}, state, { publishing: true, publishSuccess: false }), - [PUBLISH_FAIL]: state => _extends$d({}, state, { + [PUBLISH_FAIL]: state => _extends$e({}, state, { publishing: false }), - [PUBLISH_SUCCESS]: state => _extends$d({}, state, { + [PUBLISH_SUCCESS]: state => _extends$e({}, state, { publishing: false, publishSuccess: true }), @@ -5354,14 +5355,14 @@ const publishReducer = handleActions({ streamName: name }); - return _extends$d({}, defaultState$6, publishData, { + return _extends$e({}, defaultState$6, publishData, { editingURI: uri, uri: shortUri }); } }, defaultState$6); -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$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; }; const defaultState$7 = { isActive: false, // does the user have any typed text in the search input @@ -5383,23 +5384,23 @@ const defaultState$7 = { }; const searchReducer = handleActions({ - [SEARCH_START]: state => _extends$e({}, state, { + [SEARCH_START]: state => _extends$f({}, state, { searching: true }), [SEARCH_SUCCESS]: (state, action) => { const { query, uris } = action.data; - return _extends$e({}, state, { + return _extends$f({}, state, { searching: false, urisByQuery: Object.assign({}, state.urisByQuery, { [query]: uris }) }); }, - [SEARCH_FAIL]: state => _extends$e({}, state, { + [SEARCH_FAIL]: state => _extends$f({}, state, { searching: false }), - [RESOLVED_SEARCH_START]: state => _extends$e({}, state, { + [RESOLVED_SEARCH_START]: state => _extends$f({}, state, { searching: true }), [RESOLVED_SEARCH_SUCCESS]: (state, action) => { @@ -5417,24 +5418,24 @@ const searchReducer = handleActions({ // the returned number of urls is less than the page size, so we're on the last page resolvedResultsByQueryLastPageReached[query] = results.length < pageSize; - return _extends$e({}, state, { + return _extends$f({}, state, { searching: false, resolvedResultsByQuery, resolvedResultsByQueryLastPageReached }); }, - [RESOLVED_SEARCH_FAIL]: state => _extends$e({}, state, { + [RESOLVED_SEARCH_FAIL]: state => _extends$f({}, state, { searching: false }), - [UPDATE_SEARCH_QUERY]: (state, action) => _extends$e({}, state, { + [UPDATE_SEARCH_QUERY]: (state, action) => _extends$f({}, state, { searchQuery: action.data.query, isActive: true }), - [UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$e({}, state, { - suggestions: _extends$e({}, state.suggestions, { + [UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$f({}, state, { + suggestions: _extends$f({}, state.suggestions, { [action.data.query]: action.data.suggestions }) }), @@ -5442,30 +5443,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$e({}, state, { + [DISMISS_NOTIFICATION]: state => _extends$f({}, state, { isActive: false }), - [SEARCH_FOCUS]: state => _extends$e({}, state, { + [SEARCH_FOCUS]: state => _extends$f({}, state, { focused: true }), - [SEARCH_BLUR]: state => _extends$e({}, state, { + [SEARCH_BLUR]: state => _extends$f({}, state, { focused: false }), [UPDATE_SEARCH_OPTIONS]: (state, action) => { const { options: oldOptions } = state; const newOptions = action.data; - const options = _extends$e({}, oldOptions, newOptions); - return _extends$e({}, state, { + const options = _extends$f({}, oldOptions, newOptions); + return _extends$f({}, state, { options }); } }, defaultState$7); -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$g = 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$f({}, tagsMap, { + return DEFAULT_FOLLOWED_TAGS.concat(DEFAULT_KNOWN_TAGS).reduce((tagsMap, tag) => _extends$g({}, tagsMap, { [tag]: { name: tag } }), {}); } @@ -5488,7 +5489,7 @@ const tagsReducer = handleActions({ newFollowedTags.push(name); } - return _extends$f({}, state, { + return _extends$g({}, state, { followedTags: newFollowedTags }); }, @@ -5497,10 +5498,10 @@ const tagsReducer = handleActions({ const { knownTags } = state; const { name } = action.data; - let newKnownTags = _extends$f({}, knownTags); + let newKnownTags = _extends$g({}, knownTags); newKnownTags[name] = { name }; - return _extends$f({}, state, { + return _extends$g({}, state, { knownTags: newKnownTags }); }, @@ -5509,24 +5510,24 @@ const tagsReducer = handleActions({ const { knownTags, followedTags } = state; const { name } = action.data; - let newKnownTags = _extends$f({}, knownTags); + let newKnownTags = _extends$g({}, knownTags); delete newKnownTags[name]; const newFollowedTags = followedTags.filter(tag => tag !== name); - return _extends$f({}, state, { + return _extends$g({}, state, { knownTags: newKnownTags, followedTags: newFollowedTags }); }, [USER_STATE_POPULATE]: (state, action) => { const { tags } = action.data; - return _extends$f({}, state, { + return _extends$g({}, state, { followedTags: tags && tags.length ? tags : DEFAULT_FOLLOWED_TAGS }); } }, defaultState$8); -var _extends$g = 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$h = 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$9 = { blockedChannels: [] @@ -5550,13 +5551,13 @@ const blockedReducer = handleActions({ }, [USER_STATE_POPULATE]: (state, action) => { const { blocked } = action.data; - return _extends$g({}, state, { + return _extends$h({}, state, { blockedChannels: blocked && blocked.length ? blocked : state.blockedChannels }); } }, defaultState$9); -var _extends$h = 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$i = 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, @@ -5601,25 +5602,25 @@ const defaultState$a = { }; const walletReducer = handleActions({ - [FETCH_TRANSACTIONS_STARTED]: state => _extends$h({}, state, { + [FETCH_TRANSACTIONS_STARTED]: state => _extends$i({}, state, { fetchingTransactions: true }), [FETCH_TRANSACTIONS_COMPLETED]: (state, action) => { - const byId = _extends$h({}, state.transactions); + const byId = _extends$i({}, state.transactions); const { transactions } = action.data; transactions.forEach(transaction => { byId[transaction.txid] = transaction; }); - return _extends$h({}, state, { + return _extends$i({}, state, { transactions: byId, fetchingTransactions: false }); }, - [FETCH_SUPPORTS_STARTED]: state => _extends$h({}, state, { + [FETCH_SUPPORTS_STARTED]: state => _extends$i({}, state, { fetchingSupports: true }), @@ -5632,7 +5633,7 @@ const walletReducer = handleActions({ byOutpoint[`${txid}:${nout}`] = transaction; }); - return _extends$h({}, state, { supports: byOutpoint, fetchingSupports: false }); + return _extends$i({}, state, { supports: byOutpoint, fetchingSupports: false }); }, [ABANDON_SUPPORT_STARTED]: (state, action) => { @@ -5641,7 +5642,7 @@ const walletReducer = handleActions({ currentlyAbandoning[outpoint] = true; - return _extends$h({}, state, { + return _extends$i({}, state, { abandoningSupportsByOutpoint: currentlyAbandoning }); }, @@ -5654,23 +5655,23 @@ const walletReducer = handleActions({ delete currentlyAbandoning[outpoint]; delete byOutpoint[outpoint]; - return _extends$h({}, state, { + return _extends$i({}, state, { supports: byOutpoint, abandoningSupportsById: currentlyAbandoning }); }, - [GET_NEW_ADDRESS_STARTED]: state => _extends$h({}, state, { + [GET_NEW_ADDRESS_STARTED]: state => _extends$i({}, state, { gettingNewAddress: true }), [GET_NEW_ADDRESS_COMPLETED]: (state, action) => { const { address } = action.data; - return _extends$h({}, state, { gettingNewAddress: false, receiveAddress: address }); + return _extends$i({}, state, { gettingNewAddress: false, receiveAddress: address }); }, - [UPDATE_BALANCE]: (state, action) => _extends$h({}, state, { + [UPDATE_BALANCE]: (state, action) => _extends$i({}, state, { totalBalance: action.data.totalBalance, balance: action.data.balance, reservedBalance: action.data.reservedBalance, @@ -5679,32 +5680,32 @@ const walletReducer = handleActions({ tipsBalance: action.data.tipsBalance }), - [CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$h({}, state, { + [CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$i({}, state, { checkingAddressOwnership: true }), - [CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$h({}, state, { + [CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$i({}, state, { checkingAddressOwnership: false }), [SET_DRAFT_TRANSACTION_AMOUNT]: (state, action) => { const oldDraft = state.draftTransaction; - const newDraft = _extends$h({}, oldDraft, { amount: parseFloat(action.data.amount) }); + const newDraft = _extends$i({}, oldDraft, { amount: parseFloat(action.data.amount) }); - return _extends$h({}, state, { draftTransaction: newDraft }); + return _extends$i({}, state, { draftTransaction: newDraft }); }, [SET_DRAFT_TRANSACTION_ADDRESS]: (state, action) => { const oldDraft = state.draftTransaction; - const newDraft = _extends$h({}, oldDraft, { address: action.data.address }); + const newDraft = _extends$i({}, oldDraft, { address: action.data.address }); - return _extends$h({}, state, { draftTransaction: newDraft }); + return _extends$i({}, state, { draftTransaction: newDraft }); }, [SEND_TRANSACTION_STARTED]: state => { - const newDraftTransaction = _extends$h({}, state.draftTransaction, { sending: true }); + const newDraftTransaction = _extends$i({}, state.draftTransaction, { sending: true }); - return _extends$h({}, state, { draftTransaction: newDraftTransaction }); + return _extends$i({}, state, { draftTransaction: newDraftTransaction }); }, [SEND_TRANSACTION_COMPLETED]: state => Object.assign({}, state, { @@ -5717,114 +5718,114 @@ const walletReducer = handleActions({ error: action.data.error }); - return _extends$h({}, state, { draftTransaction: newDraftTransaction }); + return _extends$i({}, state, { draftTransaction: newDraftTransaction }); }, - [SUPPORT_TRANSACTION_STARTED]: state => _extends$h({}, state, { + [SUPPORT_TRANSACTION_STARTED]: state => _extends$i({}, state, { sendingSupport: true }), - [SUPPORT_TRANSACTION_COMPLETED]: state => _extends$h({}, state, { + [SUPPORT_TRANSACTION_COMPLETED]: state => _extends$i({}, state, { sendingSupport: false }), - [SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$h({}, state, { + [SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$i({}, state, { error: action.data.error, sendingSupport: false }), - [CLEAR_SUPPORT_TRANSACTION]: state => _extends$h({}, state, { + [CLEAR_SUPPORT_TRANSACTION]: state => _extends$i({}, state, { sendingSupport: false }), - [WALLET_STATUS_COMPLETED]: (state, action) => _extends$h({}, state, { + [WALLET_STATUS_COMPLETED]: (state, action) => _extends$i({}, state, { walletIsEncrypted: action.result }), - [WALLET_ENCRYPT_START]: state => _extends$h({}, state, { + [WALLET_ENCRYPT_START]: state => _extends$i({}, state, { walletEncryptPending: true, walletEncryptSucceded: null, walletEncryptResult: null }), - [WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$h({}, state, { + [WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$i({}, state, { walletEncryptPending: false, walletEncryptSucceded: true, walletEncryptResult: action.result }), - [WALLET_ENCRYPT_FAILED]: (state, action) => _extends$h({}, state, { + [WALLET_ENCRYPT_FAILED]: (state, action) => _extends$i({}, state, { walletEncryptPending: false, walletEncryptSucceded: false, walletEncryptResult: action.result }), - [WALLET_DECRYPT_START]: state => _extends$h({}, state, { + [WALLET_DECRYPT_START]: state => _extends$i({}, state, { walletDecryptPending: true, walletDecryptSucceded: null, walletDecryptResult: null }), - [WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$h({}, state, { + [WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$i({}, state, { walletDecryptPending: false, walletDecryptSucceded: true, walletDecryptResult: action.result }), - [WALLET_DECRYPT_FAILED]: (state, action) => _extends$h({}, state, { + [WALLET_DECRYPT_FAILED]: (state, action) => _extends$i({}, state, { walletDecryptPending: false, walletDecryptSucceded: false, walletDecryptResult: action.result }), - [WALLET_UNLOCK_START]: state => _extends$h({}, state, { + [WALLET_UNLOCK_START]: state => _extends$i({}, state, { walletUnlockPending: true, walletUnlockSucceded: null, walletUnlockResult: null }), - [WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$h({}, state, { + [WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$i({}, state, { walletUnlockPending: false, walletUnlockSucceded: true, walletUnlockResult: action.result }), - [WALLET_UNLOCK_FAILED]: (state, action) => _extends$h({}, state, { + [WALLET_UNLOCK_FAILED]: (state, action) => _extends$i({}, state, { walletUnlockPending: false, walletUnlockSucceded: false, walletUnlockResult: action.result }), - [WALLET_LOCK_START]: state => _extends$h({}, state, { + [WALLET_LOCK_START]: state => _extends$i({}, state, { walletLockPending: false, walletLockSucceded: null, walletLockResult: null }), - [WALLET_LOCK_COMPLETED]: (state, action) => _extends$h({}, state, { + [WALLET_LOCK_COMPLETED]: (state, action) => _extends$i({}, state, { walletLockPending: false, walletLockSucceded: true, walletLockResult: action.result }), - [WALLET_LOCK_FAILED]: (state, action) => _extends$h({}, state, { + [WALLET_LOCK_FAILED]: (state, action) => _extends$i({}, state, { walletLockPending: false, walletLockSucceded: false, walletLockResult: action.result }), - [SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$h({}, state, { + [SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$i({}, state, { transactionListFilter: action.data }), - [UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$h({}, state, { + [UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$i({}, state, { latestBlock: action.data }), - [WALLET_RESTART]: state => _extends$h({}, state, { + [WALLET_RESTART]: state => _extends$i({}, state, { walletReconnecting: true }), - [WALLET_RESTART_COMPLETED]: state => _extends$h({}, state, { + [WALLET_RESTART_COMPLETED]: state => _extends$i({}, state, { walletReconnecting: false }) }, defaultState$a); @@ -5842,14 +5843,14 @@ const makeSelectContentPositionForUri = uri => reselect.createSelector(selectSta return state.positions[id] ? state.positions[id][outpoint] : null; }); -var _extends$i = 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$j = 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$i({ + return _extends$j({ id }, params); } diff --git a/src/redux/actions/search.js b/src/redux/actions/search.js index 9701929..bee1350 100644 --- a/src/redux/actions/search.js +++ b/src/redux/actions/search.js @@ -24,12 +24,7 @@ type SearchOptions = { nsfw?: boolean, isBackgroundSearch?: boolean, resolveResults?: boolean, -} - -type AdditionalOptions = { - isBackgroundSearch: boolean, - nsfw?: boolean, -} +}; // We can't use env's because they aren't passed into node_modules let CONNECTION_STRING = 'https://lighthouse.lbry.com/'; @@ -89,11 +84,10 @@ export const doUpdateSearchQuery = (query: string, shouldSkipSuggestions: ?boole } }; - -export const doSearch = ( - rawQuery: string, - searchOptions: SearchOptions, -) => (dispatch: Dispatch, getState: GetState) => { +export const doSearch = (rawQuery: string, searchOptions: SearchOptions) => ( + dispatch: Dispatch, + getState: GetState +) => { const query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' '); const resolveResults = searchOptions && searchOptions.resolveResults; const isBackgroundSearch = (searchOptions && searchOptions.isBackgroundSearch) || false; @@ -107,9 +101,7 @@ export const doSearch = ( const state = getState(); - let queryWithOptions = makeSelectQueryWithOptions(query, searchOptions)( - state - ); + let queryWithOptions = makeSelectQueryWithOptions(query, searchOptions)(state); // If we have already searched for something, we don't need to do anything const urisForQuery = makeSelectSearchUris(queryWithOptions)(state); @@ -174,9 +166,9 @@ export const doSearch = ( export const doResolvedSearch = ( rawQuery: string, - size: ?number, // only pass in if you don't want to use the users setting (ex: related content) - from: ?number, - isBackgroundSearch: boolean = false, + size?: number, // only pass in if you don't want to use the users setting (ex: related content) + from?: number, + isBackgroundSearch?: boolean = false, options: { related_to?: string, // nsfw here @@ -196,24 +188,20 @@ export const doResolvedSearch = ( from, isBackgroundSearch, ...options, - } + }; const optionsWithoutFrom: SearchOptions = { size, isBackgroundSearch, ...options, - } + }; const state = getState(); - let queryWithOptions = makeSelectQueryWithOptions(query, optionsWithFrom)( - state - ); + let queryWithOptions = makeSelectQueryWithOptions(query, optionsWithFrom)(state); // make from null so that we can maintain a reference to the same query for multiple pages and simply append the found results - let queryWithoutFrom = makeSelectQueryWithOptions(query, optionsWithoutFrom)( - state - ); + let queryWithoutFrom = makeSelectQueryWithOptions(query, optionsWithoutFrom)(state); // If we have already searched for something, we don't need to do anything // TODO: Tweak this check for multiple page results @@ -268,10 +256,10 @@ export const doBlurSearchInput = () => (dispatch: Dispatch) => type: ACTIONS.SEARCH_BLUR, }); -export const doUpdateSearchOptions = (newOptions: SearchOptions, additionalOptions: AdditionalOptions) => ( - dispatch: Dispatch, - getState: GetState -) => { +export const doUpdateSearchOptions = ( + newOptions: SearchOptions, + additionalOptions: SearchOptions +) => (dispatch: Dispatch, getState: GetState) => { const state = getState(); const searchValue = selectSearchValue(state); diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index c7f489b..73a3018 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -279,8 +279,8 @@ export const makeSelectDateForUri = (uri: string) => (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta && claim.meta.creation_timestamp - ? claim.meta.creation_timestamp * 1000 - : null); + ? claim.meta.creation_timestamp * 1000 + : null); if (!timestamp) { return undefined; } @@ -530,7 +530,12 @@ export const makeSelectRecommendedContentForUri = (uri: string) => return; } - const options = { related_to: claim.claim_id, isBackgroundSearch: true }; + const options: { + related_to?: string, + nsfw?: boolean, + isBackgroundSearch?: boolean, + } = { related_to: claim.claim_id, isBackgroundSearch: true }; + if (!isMature) { options['nsfw'] = false; } @@ -681,7 +686,11 @@ export const makeSelectResolvedRecommendedContentForUri = (uri: string, size: nu return; } - const options = { related_to: claim.claim_id, isBackgroundSearch: true } + const options: { + related_to?: string, + nsfw?: boolean, + isBackgroundSearch?: boolean, + } = { related_to: claim.claim_id, isBackgroundSearch: true }; if (!isMature) { options['nsfw'] = false; } From f0a0a59c4c4cedbbe4c50ec423c5b2e202cbe800 Mon Sep 17 00:00:00 2001 From: Thomas Zarebczan Date: Sat, 1 Feb 2020 13:33:04 -0500 Subject: [PATCH 33/34] add known tags --- dist/bundle.es.js | 2 +- src/constants/tags.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 07d9eea..9153398 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -827,7 +827,7 @@ const DEFAULT_FOLLOWED_TAGS = ['art', 'automotive', 'blockchain', 'comedy', 'eco const MATURE_TAGS = ['porn', 'nsfw', 'mature', 'xxx']; -const DEFAULT_KNOWN_TAGS = ['gaming', 'pop culture', 'Entertainment', 'technology', 'music', 'funny', 'Education', 'learning', 'news', 'gameplay', 'nature', 'beliefs', 'comedy', 'games', 'sony interactive entertainment', 'film & animation', 'game', 'weapons', "let's play", 'blockchain', 'video game', 'sports', 'walkthrough', 'ps4live', 'art', 'pc', 'minecraft', 'playthrough', 'economics', 'automotive', 'play', 'ps4share', 'tutorial', 'twitch', 'how to', 'ps4', 'bitcoin', 'fortnite', 'commentary', 'lets play', 'fun', 'politics', 'xbox', 'autos & vehicles', 'Travel & Events', 'food', 'science', 'xbox one', 'liberal', 'democrat', 'progressive', 'survival', 'Nonprofits & Activism', 'cryptocurrency', 'playstation', 'nintendo', 'government', 'steam', 'podcast', 'gamer', 'horror', 'conservative', 'reaction', 'trailer', 'love', 'cnn', 'republican', 'political', 'hangoutsonair', 'hoa', 'msnbc', 'cbs', 'anime', 'donald trump', 'fiction', 'fox news', 'crypto', 'ethereum', 'call of duty', 'android', 'multiplayer', 'epic', 'rpg', 'adventure', 'secular talk', 'btc', 'atheist', 'atheism', 'video games', 'ps3', 'cod', 'online', 'agnostic', 'movie', 'fps', 'lets', 'mod', 'world', 'reviews', 'sharefactory', 'space', 'pokemon', 'stream', 'hilarious', 'lol', 'sony', 'god', "let's", 'dance', 'pvp', 'tech', 'strategy', 'zombies', 'fail', 'film', 'xbox 360', 'animation', 'unboxing', 'money', 'how', 'travel', 'wwe', 'mods', 'indie', 'pubg', 'ios', 'history', 'rap', 'sony computer entertainment', 'mobile', 'trump', 'hack', 'flat earth', 'trap', 'humor', 'vlogging', 'fox', 'news radio', 'facebook', 'edm', 'fitness', 'vaping', 'hip hop', 'secular', 'jesus', 'song', 'vape', 'guitar', 'remix', 'mining', 'daily', 'diy', 'pets & animals', 'videogame', 'death', 'funny moments', 'religion', 'media', 'viral', 'war', 'nbc', 'freedom', 'gold', 'family', 'meme', 'zombie', 'photography', 'chill', 'sniper', 'computer', 'iphone', 'dragon', 'bible', 'pro', 'overwatch', 'litecoin', 'gta', 'house', 'fire', 'bass', 'bitcoin news', 'truth', 'crash', 'mario', 'league of legends', 'wii', 'mmorpg', 'grand theft auto v', 'health', 'marvel', 'racing', 'apple', 'instrumental', 'earth', 'destiny', 'satire', 'race', 'training', 'electronic', 'boss', 'roblox', 'family friendly', 'california', 'react', 'christian', 'mmo', 'twitter', 'help', 'star', 'cars', 'random', 'top 10', 'ninja', 'guns', 'linux', 'lessons', 'vegan', 'future', 'dota 2', 'studio', 'star wars', 'gta 5', 'shooting', 'nasa', 'rock', 'league', 'subscribe', 'water', 'gta v', 'car', 'samsung', 'music video', 'skyrim', 'dog', 'comics', 'shooter game', 'bo3', 'halloween', 'liberty', 'eth', 'conspiracy', 'knife', 'fashion', 'stories', 'vapor', 'nvidia', 'cute', 'beat', 'nintendo switch', 'fantasy', 'christmas', 'world of warcraft', 'industry', 'cartoon', 'crypto news', 'garden', 'animals', 'windows', 'happy', 'magic', 'memes', 'design', 'tactical', 'fallout 4', 'puzzle', 'parody', 'rv', 'beats', 'fortnite battle royale', 'building', 'disney', 'drone', 'ps2', 'beach', 'metal', 'christianity', 'business', 'mix', 'bo2', 'cover', 'senate', '4k', 'united states', 'final', 'hero', 'playing', 'dlc', 'ubisoft', 'halo', 'pc gaming', 'raw', 'investing', 'online learning', 'software', 'ark', 'mojang', 'console', 'battle royale', 'canon', 'microsoft', 'camping', 'cryptocurrency news', 'ufo', 'progressive talk', 'switch', 'fpv', 'arcade', 'school', 'driving', 'bodybuilding', 'drama', 'retro', 'science fiction', 'eggs', 'australia', 'modded', 'rainbow', 'gamers', 'resident evil', 'drawing', 'brasil', 'england', 'hillary clinton', 'singing', 'final fantasy', 'hiphop', 'video blog', 'mature', 'quad', 'noob', 'simulation', 'illuminati', 'poetry', 'dayz', 'manga', 'howto', 'insane', 'xbox360', 'press', 'special', 'church', 'ico', 'weird', 'libertarian', 'crafting', 'level', 'comic', 'sandbox', 'daily vlog', 'outdoor', 'black ops', 'sound', 'christ', 'duty', 'Juvenile fiction', 'pc game', 'how-to', 'ww2', 'creepy', 'artist', 'galaxy', 'destiny 2', 'new music', 'quest', 'lee', 'pacman', 'super smash bros', 'day', 'survival horror', 'patreon', 'bitcoin price', 'trending', 'open world', 'wii u', 'dope', 'reaper', 'sniping', 'dubstep', 'truck', 'planet', 'dc', 'amazon', 'spirituality', 'universe', 'video game culture', 'community', 'cat', 'aliens', 'tourism', 'altcoins', 'style', 'travel trailer', 'rda', '5859dfec-026f-46ba-bea0-02bf43aa1a6f', 'gun', 'secret', 'far cry 5', 'auto', 'culture', 'dj', 'mw2', 'lord', 'full time rving', 'role-playing game', 'prank', 'grand theft auto', 'master', 'wrestling', 'sci-fi', 'workout', 'ghost', 'fake news', 'silly', 'season', 'bo4', 'trading', 'extreme', 'economy', 'combat', 'plays', 'muslim', 'pubg mobile', 'clips', 'bo1', 'paypal', 'sims', 'exploration', 'light', 'ripple', 'paranormal', 'football', 'capcom', 'rta', 'discord', 'action role-playing game', 'playthrough part', 'batman', 'player', 'server', 'anarchy', 'military', 'playlist', 'cosplay', 'rv park', 'rant', 'edit', 'germany', 'reading', 'chris', 'flash', 'loot', 'bitcoin gratis', 'game reviews', 'movies', 'stupid', 'latest news', 'squad gameplay', 'guru', 'timelapse', 'black ops 3', 'holiday', 'soul', 'motivation', 'mw3', 'vacation', 'sega', '19th century', 'pop', 'sims 4', 'post', 'smok', 'island', 'scotland', 'paladins', 'warrior', 'creepypasta', 'role-playing video game', 'solar', 'vr', 'animal', 'peace', 'consciousness', 'dota', 'audio', 'mass effect', 'Humour', 'first look', 'videogames', 'future bass', 'freestyle', 'hardcore', 'portugal', 'dantdm', 'teaser', 'lbry']; +const DEFAULT_KNOWN_TAGS = ['free speech', 'censorship', 'gaming', 'pop culture', 'Entertainment', 'technology', 'music', 'funny', 'Education', 'learning', 'news', 'gameplay', 'nature', 'beliefs', 'comedy', 'games', 'sony interactive entertainment', 'film & animation', 'game', 'weapons', "let's play", 'blockchain', 'video game', 'sports', 'walkthrough', 'ps4live', 'art', 'pc', 'minecraft', 'playthrough', 'economics', 'automotive', 'play', 'ps4share', 'tutorial', 'twitch', 'how to', 'ps4', 'bitcoin', 'fortnite', 'commentary', 'lets play', 'fun', 'politics', 'xbox', 'autos & vehicles', 'Travel & Events', 'food', 'science', 'xbox one', 'liberal', 'democrat', 'progressive', 'survival', 'Nonprofits & Activism', 'cryptocurrency', 'playstation', 'nintendo', 'government', 'steam', 'podcast', 'gamer', 'horror', 'conservative', 'reaction', 'trailer', 'love', 'cnn', 'republican', 'political', 'hangoutsonair', 'hoa', 'msnbc', 'cbs', 'anime', 'donald trump', 'fiction', 'fox news', 'crypto', 'ethereum', 'call of duty', 'android', 'multiplayer', 'epic', 'rpg', 'adventure', 'secular talk', 'btc', 'atheist', 'atheism', 'video games', 'ps3', 'cod', 'online', 'agnostic', 'movie', 'fps', 'lets', 'mod', 'world', 'reviews', 'sharefactory', 'space', 'pokemon', 'stream', 'hilarious', 'lol', 'sony', 'god', "let's", 'dance', 'pvp', 'tech', 'strategy', 'zombies', 'fail', 'film', 'xbox 360', 'animation', 'unboxing', 'money', 'how', 'travel', 'wwe', 'mods', 'indie', 'pubg', 'ios', 'history', 'rap', 'sony computer entertainment', 'mobile', 'trump', 'hack', 'flat earth', 'trap', 'humor', 'vlogging', 'fox', 'news radio', 'facebook', 'edm', 'fitness', 'vaping', 'hip hop', 'secular', 'jesus', 'song', 'vape', 'guitar', 'remix', 'mining', 'daily', 'diy', 'pets & animals', 'videogame', 'death', 'funny moments', 'religion', 'media', 'viral', 'war', 'nbc', 'freedom', 'gold', 'family', 'meme', 'zombie', 'photography', 'chill', 'sniper', 'computer', 'iphone', 'dragon', 'bible', 'pro', 'overwatch', 'litecoin', 'gta', 'house', 'fire', 'bass', 'bitcoin news', 'truth', 'crash', 'mario', 'league of legends', 'wii', 'mmorpg', 'grand theft auto v', 'health', 'marvel', 'racing', 'apple', 'instrumental', 'earth', 'destiny', 'satire', 'race', 'training', 'electronic', 'boss', 'roblox', 'family friendly', 'california', 'react', 'christian', 'mmo', 'twitter', 'help', 'star', 'cars', 'random', 'top 10', 'ninja', 'guns', 'linux', 'lessons', 'vegan', 'future', 'dota 2', 'studio', 'star wars', 'gta 5', 'shooting', 'nasa', 'rock', 'league', 'subscribe', 'water', 'gta v', 'car', 'samsung', 'music video', 'skyrim', 'dog', 'comics', 'shooter game', 'bo3', 'halloween', 'liberty', 'eth', 'conspiracy', 'knife', 'fashion', 'stories', 'vapor', 'nvidia', 'cute', 'beat', 'nintendo switch', 'fantasy', 'christmas', 'world of warcraft', 'industry', 'cartoon', 'crypto news', 'garden', 'animals', 'windows', 'happy', 'magic', 'memes', 'design', 'tactical', 'fallout 4', 'puzzle', 'parody', 'rv', 'beats', 'fortnite battle royale', 'building', 'disney', 'drone', 'ps2', 'beach', 'metal', 'christianity', 'business', 'mix', 'bo2', 'cover', 'senate', '4k', 'united states', 'final', 'hero', 'playing', 'dlc', 'ubisoft', 'halo', 'pc gaming', 'raw', 'investing', 'online learning', 'software', 'ark', 'mojang', 'console', 'battle royale', 'canon', 'microsoft', 'camping', 'cryptocurrency news', 'ufo', 'progressive talk', 'switch', 'fpv', 'arcade', 'school', 'driving', 'bodybuilding', 'drama', 'retro', 'science fiction', 'eggs', 'australia', 'modded', 'rainbow', 'gamers', 'resident evil', 'drawing', 'brasil', 'england', 'hillary clinton', 'singing', 'final fantasy', 'hiphop', 'video blog', 'mature', 'quad', 'noob', 'simulation', 'illuminati', 'poetry', 'dayz', 'manga', 'howto', 'insane', 'xbox360', 'press', 'special', 'church', 'ico', 'weird', 'libertarian', 'crafting', 'level', 'comic', 'sandbox', 'daily vlog', 'outdoor', 'black ops', 'sound', 'christ', 'duty', 'Juvenile fiction', 'pc game', 'how-to', 'ww2', 'creepy', 'artist', 'galaxy', 'destiny 2', 'new music', 'quest', 'lee', 'pacman', 'super smash bros', 'day', 'survival horror', 'patreon', 'bitcoin price', 'trending', 'open world', 'wii u', 'dope', 'reaper', 'sniping', 'dubstep', 'truck', 'planet', 'dc', 'amazon', 'spirituality', 'universe', 'video game culture', 'community', 'cat', 'aliens', 'tourism', 'altcoins', 'style', 'travel trailer', 'rda', '5859dfec-026f-46ba-bea0-02bf43aa1a6f', 'gun', 'secret', 'far cry 5', 'auto', 'culture', 'dj', 'mw2', 'lord', 'full time rving', 'role-playing game', 'prank', 'grand theft auto', 'master', 'wrestling', 'sci-fi', 'workout', 'ghost', 'fake news', 'silly', 'season', 'bo4', 'trading', 'extreme', 'economy', 'combat', 'plays', 'muslim', 'pubg mobile', 'clips', 'bo1', 'paypal', 'sims', 'exploration', 'light', 'ripple', 'paranormal', 'football', 'capcom', 'rta', 'discord', 'action role-playing game', 'playthrough part', 'batman', 'player', 'server', 'anarchy', 'military', 'playlist', 'cosplay', 'rv park', 'rant', 'edit', 'germany', 'reading', 'chris', 'flash', 'loot', 'bitcoin gratis', 'game reviews', 'movies', 'stupid', 'latest news', 'squad gameplay', 'guru', 'timelapse', 'black ops 3', 'holiday', 'soul', 'motivation', 'mw3', 'vacation', 'sega', '19th century', 'pop', 'sims 4', 'post', 'smok', 'island', 'scotland', 'paladins', 'warrior', 'creepypasta', 'role-playing video game', 'solar', 'vr', 'animal', 'peace', 'consciousness', 'dota', 'audio', 'mass effect', 'Humour', 'first look', 'videogames', 'future bass', 'freestyle', 'hardcore', 'portugal', 'dantdm', 'teaser', 'lbry']; // diff --git a/src/constants/tags.js b/src/constants/tags.js index e44fe37..3a1e26d 100644 --- a/src/constants/tags.js +++ b/src/constants/tags.js @@ -16,6 +16,8 @@ export const DEFAULT_FOLLOWED_TAGS = [ export const MATURE_TAGS = ['porn', 'nsfw', 'mature', 'xxx']; export const DEFAULT_KNOWN_TAGS = [ + 'free speech', + 'censorship', 'gaming', 'pop culture', 'Entertainment', From afc76b08d705e961f91cc319f06d1c8c40333659 Mon Sep 17 00:00:00 2001 From: YULIUS KURNIAWAN KRISTIANTO Date: Mon, 3 Feb 2020 05:55:34 +0700 Subject: [PATCH 34/34] Update LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 200acb5..e8be4ab 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2017-2019 LBRY Inc +Copyright (c) 2017-2020 LBRY Inc Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish,