Merge pull request #148 from lbryio/comment-redux

redux comments DRAFT WIP
This commit is contained in:
Sean Yesmunt 2019-06-26 19:25:38 -04:00 committed by GitHub
commit 1415935006
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 419 additions and 10 deletions

186
dist/bundle.es.js vendored
View file

@ -102,6 +102,14 @@ const CLAIM_SEARCH_STARTED = 'CLAIM_SEARCH_STARTED';
const CLAIM_SEARCH_COMPLETED = 'CLAIM_SEARCH_COMPLETED';
const CLAIM_SEARCH_FAILED = 'CLAIM_SEARCH_FAILED';
// Comments
const COMMENT_LIST_STARTED = 'COMMENT_LIST_STARTED';
const COMMENT_LIST_COMPLETED = 'COMMENT_LIST_COMPLETED';
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';
// Files
const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED';
@ -318,6 +326,12 @@ var action_types = /*#__PURE__*/Object.freeze({
CLAIM_SEARCH_STARTED: CLAIM_SEARCH_STARTED,
CLAIM_SEARCH_COMPLETED: CLAIM_SEARCH_COMPLETED,
CLAIM_SEARCH_FAILED: CLAIM_SEARCH_FAILED,
COMMENT_LIST_STARTED: COMMENT_LIST_STARTED,
COMMENT_LIST_COMPLETED: COMMENT_LIST_COMPLETED,
COMMENT_LIST_FAILED: COMMENT_LIST_FAILED,
COMMENT_CREATE_STARTED: COMMENT_CREATE_STARTED,
COMMENT_CREATE_COMPLETED: COMMENT_CREATE_COMPLETED,
COMMENT_CREATE_FAILED: COMMENT_CREATE_FAILED,
FILE_LIST_STARTED: FILE_LIST_STARTED,
FILE_LIST_SUCCEEDED: FILE_LIST_SUCCEEDED,
FETCH_FILE_INFO_STARTED: FETCH_FILE_INFO_STARTED,
@ -676,6 +690,9 @@ const Lbry = {
sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params),
sync_apply: (params = {}) => daemonCallWithResult('sync_apply', params),
// Comments
comment_list: (params = {}) => daemonCallWithResult('comment_list', params),
comment_create: (params = {}) => daemonCallWithResult('comment_create', params),
// Connect to the sdk
connect: () => {
if (Lbry.connectPromise === null) {
@ -2761,6 +2778,72 @@ const doDeleteTag = name => ({
}
});
//
function doCommentList(uri) {
return (dispatch, getState) => {
const state = getState();
const claim = selectClaimsByUri(state)[uri];
const claimId = claim ? claim.claim_id : null;
dispatch({
type: COMMENT_LIST_STARTED
});
lbryProxy.comment_list({
claim_id: claimId
}).then(results => {
dispatch({
type: COMMENT_LIST_COMPLETED,
data: {
comments: results,
claimId: claimId,
uri: uri
}
});
}).catch(error => {
console.log(error);
dispatch({
type: COMMENT_LIST_FAILED,
data: error
});
});
};
}
function doCommentCreate(comment = '', claim_id = '', channel, parent_id) {
return (dispatch, getState) => {
const state = getState();
dispatch({
type: COMMENT_CREATE_STARTED
});
const myChannels = selectMyChannelClaims(state);
const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel);
const channel_id = namedChannelClaim ? namedChannelClaim.claim_id : null;
return lbryProxy.comment_create({
comment,
claim_id,
channel_id
}).then(result => {
dispatch({
type: COMMENT_CREATE_COMPLETED,
data: {
comment: result,
claimId: claim_id
}
});
}).catch(error => {
dispatch({
type: COMMENT_CREATE_FAILED,
data: error
});
dispatch(doToast({
message: 'Oops, someone broke comments.',
isError: true
}));
});
};
}
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 reducers = {};
@ -3726,6 +3809,60 @@ function contentReducer(state = defaultState$6, action) {
var _extends$b = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
const defaultState$7 = {
byId: {},
commentsByUri: {},
isLoading: false
};
const commentReducer = handleActions({
[COMMENT_CREATE_STARTED]: (state, action) => _extends$b({}, state, {
isLoading: true
}),
[COMMENT_CREATE_FAILED]: (state, action) => _extends$b({}, state, {
isLoading: false
}),
[COMMENT_CREATE_COMPLETED]: (state, action) => {
const { comment, claimId } = action.data;
const byId = Object.assign({}, state.byId);
const comments = byId[claimId];
const newComments = comments.slice();
newComments.unshift(comment);
byId[claimId] = newComments;
return _extends$b({}, state, {
byId
});
},
[COMMENT_LIST_STARTED]: state => _extends$b({}, state, { isLoading: true }),
[COMMENT_LIST_COMPLETED]: (state, action) => {
const { comments, claimId, uri } = action.data;
const byId = Object.assign({}, state.byId);
const commentsByUri = Object.assign({}, state.commentsByUri);
if (comments['items']) {
byId[claimId] = comments['items'];
commentsByUri[uri] = claimId;
}
return _extends$b({}, state, {
byId,
commentsByUri,
isLoading: false
});
},
[COMMENT_LIST_FAILED]: (state, action) => _extends$b({}, state, {
isLoading: false
})
}, defaultState$7);
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 tagsReducerBuilder = defaultState => handleActions({
[TOGGLE_TAG_FOLLOW]: (state, action) => {
const { followedTags } = state;
@ -3739,7 +3876,7 @@ const tagsReducerBuilder = defaultState => handleActions({
newFollowedTags.push(name);
}
return _extends$b({}, state, {
return _extends$c({}, state, {
followedTags: newFollowedTags
});
},
@ -3748,10 +3885,10 @@ const tagsReducerBuilder = defaultState => handleActions({
const { knownTags } = state;
const { name } = action.data;
let newKnownTags = _extends$b({}, knownTags);
let newKnownTags = _extends$c({}, knownTags);
newKnownTags[name] = { name };
return _extends$b({}, state, {
return _extends$c({}, state, {
knownTags: newKnownTags
});
},
@ -3760,11 +3897,11 @@ const tagsReducerBuilder = defaultState => handleActions({
const { knownTags, followedTags } = state;
const { name } = action.data;
let newKnownTags = _extends$b({}, knownTags);
let newKnownTags = _extends$c({}, knownTags);
delete newKnownTags[name];
const newFollowedTags = followedTags.filter(tag => tag !== name);
return _extends$b({}, state, {
return _extends$c({}, state, {
knownTags: newKnownTags,
followedTags: newFollowedTags
});
@ -3782,14 +3919,14 @@ const makeSelectContentPositionForUri = uri => reselect.createSelector(selectSta
return state.positions[id] ? state.positions[id][outpoint] : null;
});
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 selectState$6 = state => state.notifications || {};
const selectToast = reselect.createSelector(selectState$6, state => {
if (state.toasts.length) {
const { id, params } = state.toasts[0];
return _extends$c({
return _extends$d({
id
}, params);
}
@ -3810,11 +3947,36 @@ const selectError = reselect.createSelector(selectState$6, state => {
//
const selectState$7 = state => state.tags || {};
const selectState$7 = state => state.comments || {};
const selectKnownTagsByName = reselect.createSelector(selectState$7, state => state.knownTags);
const selectCommentsById = reselect.createSelector(selectState$7, state => state.byId || {});
const selectFollowedTagsList = reselect.createSelector(selectState$7, state => state.followedTags);
const selectCommentsByUri = reselect.createSelector(selectState$7, state => {
const byUri = state.commentsByUri || {};
const comments = {};
Object.keys(byUri).forEach(uri => {
const claimId = byUri[uri];
if (claimId === null) {
comments[uri] = null;
} else {
comments[uri] = claimId;
}
});
return comments;
});
const makeSelectCommentsForUri = uri => reselect.createSelector(selectCommentsById, selectCommentsByUri, (byId, byUri) => {
const claimId = byUri[uri];
return byId && byId[claimId];
});
//
const selectState$8 = state => state.tags || {};
const selectKnownTagsByName = reselect.createSelector(selectState$8, state => state.knownTags);
const selectFollowedTagsList = reselect.createSelector(selectState$8, state => state.followedTags);
const selectFollowedTags = reselect.createSelector(selectFollowedTagsList, followedTags => followedTags.map(tag => ({ name: tag })).sort((a, b) => a.name.localeCompare(b.name)));
@ -3844,6 +4006,7 @@ exports.TRANSACTIONS = transaction_types;
exports.batchActions = batchActions;
exports.buildURI = buildURI;
exports.claimsReducer = claimsReducer;
exports.commentReducer = commentReducer;
exports.contentReducer = contentReducer;
exports.convertToShareLink = convertToShareLink;
exports.creditsToString = creditsToString;
@ -3853,6 +4016,8 @@ exports.doBalanceSubscribe = doBalanceSubscribe;
exports.doBlurSearchInput = doBlurSearchInput;
exports.doCheckAddressIsMine = doCheckAddressIsMine;
exports.doClaimSearch = doClaimSearch;
exports.doCommentCreate = doCommentCreate;
exports.doCommentList = doCommentList;
exports.doCreateChannel = doCreateChannel;
exports.doDeletePurchasedUri = doDeletePurchasedUri;
exports.doDeleteTag = doDeleteTag;
@ -3906,6 +4071,7 @@ exports.makeSelectClaimIsNsfw = makeSelectClaimIsNsfw;
exports.makeSelectClaimIsPending = makeSelectClaimIsPending;
exports.makeSelectClaimsInChannelForCurrentPageState = makeSelectClaimsInChannelForCurrentPageState;
exports.makeSelectClaimsInChannelForPage = makeSelectClaimsInChannelForPage;
exports.makeSelectCommentsForUri = makeSelectCommentsForUri;
exports.makeSelectContentPositionForUri = makeSelectContentPositionForUri;
exports.makeSelectContentTypeForUri = makeSelectContentTypeForUri;
exports.makeSelectCoverForUri = makeSelectCoverForUri;

18
dist/flow-typed/Comment.js vendored Normal file
View file

@ -0,0 +1,18 @@
declare type Comment = {
author: string,
claim_index?: number,
comment_id?: number,
downvotes?: number,
message: string,
omitted?: number,
reply_count?: number,
time_posted?: number,
upvotes?: number,
parent_id?: number,
};
declare type CommentsState = {
byId: {},
isLoading: boolean,
commentsByUri: { [string]: string },
}

View file

@ -105,6 +105,9 @@ declare type ChannelCreateResponse = GenericTxResponse & {
outputs: Array<ChannelClaim>,
};
declare type CommentCreateResponse = Comment;
declare type CommentListResponse = Array<Comment>;
declare type ChannelListResponse = Array<ChannelClaim>;
declare type FileListResponse = Array<FileListItem>;
@ -184,6 +187,9 @@ declare type LbryTypes = {
blob_delete: (params: {}) => Promise<string>,
blob_list: (params: {}) => Promise<BlobListResponse>,
// Commenting
comment_list: (params: {}) => Promise<CommentListResponse>,
comment_create: (params: {}) => Promise<CommentCreateResponse>,
// Wallet utilities
account_balance: (params: {}) => Promise<string>,
account_decrypt: (prams: {}) => Promise<boolean>,

18
flow-typed/Comment.js vendored Normal file
View file

@ -0,0 +1,18 @@
declare type Comment = {
author: string,
claim_index?: number,
comment_id?: number,
downvotes?: number,
message: string,
omitted?: number,
reply_count?: number,
time_posted?: number,
upvotes?: number,
parent_id?: number,
};
declare type CommentsState = {
byId: {},
isLoading: boolean,
commentsByUri: { [string]: string },
}

6
flow-typed/Lbry.js vendored
View file

@ -105,6 +105,9 @@ declare type ChannelCreateResponse = GenericTxResponse & {
outputs: Array<ChannelClaim>,
};
declare type CommentCreateResponse = Comment;
declare type CommentListResponse = Array<Comment>;
declare type ChannelListResponse = Array<ChannelClaim>;
declare type FileListResponse = Array<FileListItem>;
@ -184,6 +187,9 @@ declare type LbryTypes = {
blob_delete: (params: {}) => Promise<string>,
blob_list: (params: {}) => Promise<BlobListResponse>,
// Commenting
comment_list: (params: {}) => Promise<CommentListResponse>,
comment_create: (params: {}) => Promise<CommentCreateResponse>,
// Wallet utilities
account_balance: (params: {}) => Promise<string>,
account_decrypt: (prams: {}) => Promise<boolean>,

View file

@ -92,6 +92,14 @@ export const CLAIM_SEARCH_STARTED = 'CLAIM_SEARCH_STARTED';
export const CLAIM_SEARCH_COMPLETED = 'CLAIM_SEARCH_COMPLETED';
export const CLAIM_SEARCH_FAILED = 'CLAIM_SEARCH_FAILED';
// Comments
export const COMMENT_LIST_STARTED = 'COMMENT_LIST_STARTED';
export const COMMENT_LIST_COMPLETED = 'COMMENT_LIST_COMPLETED';
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';
// Files
export const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
export const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED';

View file

@ -90,6 +90,8 @@ export {
export { doToggleTagFollow, doAddTag, doDeleteTag } from 'redux/actions/tags';
export { doCommentList, doCommentCreate } from 'redux/actions/comments';
// utils
export { batchActions } from 'util/batchActions';
export { parseQueryParams, toQueryString } from 'util/query_params';
@ -104,6 +106,7 @@ export { notificationsReducer } from 'redux/reducers/notifications';
export { searchReducer } from 'redux/reducers/search';
export { walletReducer } from 'redux/reducers/wallet';
export { contentReducer } from 'redux/reducers/content';
export { commentReducer } from 'redux/reducers/comments';
export { tagsReducerBuilder } from 'redux/reducers/tags';
// selectors
@ -170,6 +173,8 @@ export {
selectLastClaimSearchUris,
} from 'redux/selectors/claims';
export { makeSelectCommentsForUri } from 'redux/selectors/comments';
export {
makeSelectFileInfoForUri,
makeSelectDownloadingForUri,

View file

@ -100,6 +100,9 @@ const Lbry: LbryTypes = {
sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params),
sync_apply: (params = {}) => daemonCallWithResult('sync_apply', params),
// Comments
comment_list: (params = {}) => daemonCallWithResult('comment_list', params),
comment_create: (params = {}) => daemonCallWithResult('comment_create', params),
// Connect to the sdk
connect: () => {
if (Lbry.connectPromise === null) {

View file

@ -0,0 +1,80 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import Lbry from 'lbry';
import { selectClaimsByUri, selectMyChannelClaims } from 'redux/selectors/claims';
import { doToast } from 'redux/actions/notifications';
export function doCommentList(uri: string) {
return (dispatch: Dispatch, getState: GetState) => {
const state = getState();
const claim = selectClaimsByUri(state)[uri];
const claimId = claim ? claim.claim_id : null;
dispatch({
type: ACTIONS.COMMENT_LIST_STARTED,
});
Lbry.comment_list({
claim_id: claimId,
})
.then((results: CommentListResponse) => {
dispatch({
type: ACTIONS.COMMENT_LIST_COMPLETED,
data: {
comments: results,
claimId: claimId,
uri: uri,
},
});
})
.catch(error => {
console.log(error);
dispatch({
type: ACTIONS.COMMENT_LIST_FAILED,
data: error,
});
});
};
}
export function doCommentCreate(
comment: string = '',
claim_id: string = '',
channel: ?string,
parent_id?: number
) {
return (dispatch: Dispatch, getState: GetState) => {
const state = getState();
dispatch({
type: ACTIONS.COMMENT_CREATE_STARTED,
});
const myChannels = selectMyChannelClaims(state);
const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel);
const channel_id = namedChannelClaim ? namedChannelClaim.claim_id : null;
return Lbry.comment_create({
comment,
claim_id,
channel_id,
})
.then((result: Comment) => {
dispatch({
type: ACTIONS.COMMENT_CREATE_COMPLETED,
data: {
comment: result,
claimId: claim_id,
},
});
})
.catch(error => {
dispatch({
type: ACTIONS.COMMENT_CREATE_FAILED,
data: error,
});
dispatch(
doToast({
message: 'Oops, someone broke comments.',
isError: true,
})
);
});
};
}

View file

@ -0,0 +1,63 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import { handleActions } from 'util/redux-utils';
const defaultState: CommentsState = {
byId: {},
commentsByUri: {},
isLoading: false,
};
export const commentReducer = handleActions(
{
[ACTIONS.COMMENT_CREATE_STARTED]: (state: CommentsState, action: any): CommentsState => ({
...state,
isLoading: true,
}),
[ACTIONS.COMMENT_CREATE_FAILED]: (state: CommentsState, action: any) => ({
...state,
isLoading: false,
}),
[ACTIONS.COMMENT_CREATE_COMPLETED]: (state: CommentsState, action: any): CommentsState => {
const { comment, claimId }: any = action.data;
const byId = Object.assign({}, state.byId);
const comments = byId[claimId];
const newComments = comments.slice();
newComments.unshift(comment);
byId[claimId] = newComments;
return {
...state,
byId,
};
},
[ACTIONS.COMMENT_LIST_STARTED]: state => ({ ...state, isLoading: true }),
[ACTIONS.COMMENT_LIST_COMPLETED]: (state: CommentsState, action: any) => {
const { comments, claimId, uri } = action.data;
const byId = Object.assign({}, state.byId);
const commentsByUri = Object.assign({}, state.commentsByUri);
if (comments['items']) {
byId[claimId] = comments['items'];
commentsByUri[uri] = claimId;
}
return {
...state,
byId,
commentsByUri,
isLoading: false,
};
},
[ACTIONS.COMMENT_LIST_FAILED]: (state: CommentsState, action: any) => ({
...state,
isLoading: false,
}),
},
defaultState
);

View file

@ -0,0 +1,36 @@
// @flow
import { createSelector } from 'reselect';
const selectState = state => state.comments || {};
export const selectCommentsById = createSelector(
selectState,
state => state.byId || {}
);
export const selectCommentsByUri = createSelector(
selectState,
state => {
const byUri = state.commentsByUri || {};
const comments = {};
Object.keys(byUri).forEach(uri => {
const claimId = byUri[uri];
if (claimId === null) {
comments[uri] = null;
} else {
comments[uri] = claimId;
}
});
return comments;
}
);
export const makeSelectCommentsForUri = (uri: string) =>
createSelector(
selectCommentsById,
selectCommentsByUri,
(byId, byUri) => {
const claimId = byUri[uri];
return byId && byId[claimId];
}
);