changes for comments

This commit is contained in:
Jessop Breth 2019-06-11 21:14:37 -04:00 committed by Sean Yesmunt
parent 3c862e72b3
commit 862ea67680
11 changed files with 429 additions and 3 deletions

184
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_COMPLETED = 'CLAIM_SEARCH_COMPLETED';
const CLAIM_SEARCH_FAILED = 'CLAIM_SEARCH_FAILED'; 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_UPDATED = 'COMMENT_LIST_UPDATED';
const COMMENT_CREATE_STARTED = 'COMMENT_CREATE_STARTED';
const COMMENT_CREATE_COMPLETED = 'COMMENT_CREATE_COMPLETED';
const COMMENT_CREATE_FAILED = 'COMMENT_CREATE_FAILED';
// Files // Files
const FILE_LIST_STARTED = 'FILE_LIST_STARTED'; const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED'; 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_STARTED: CLAIM_SEARCH_STARTED,
CLAIM_SEARCH_COMPLETED: CLAIM_SEARCH_COMPLETED, CLAIM_SEARCH_COMPLETED: CLAIM_SEARCH_COMPLETED,
CLAIM_SEARCH_FAILED: CLAIM_SEARCH_FAILED, CLAIM_SEARCH_FAILED: CLAIM_SEARCH_FAILED,
COMMENT_LIST_STARTED: COMMENT_LIST_STARTED,
COMMENT_LIST_COMPLETED: COMMENT_LIST_COMPLETED,
COMMENT_LIST_UPDATED: COMMENT_LIST_UPDATED,
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_STARTED: FILE_LIST_STARTED,
FILE_LIST_SUCCEEDED: FILE_LIST_SUCCEEDED, FILE_LIST_SUCCEEDED: FILE_LIST_SUCCEEDED,
FETCH_FILE_INFO_STARTED: FETCH_FILE_INFO_STARTED, FETCH_FILE_INFO_STARTED: FETCH_FILE_INFO_STARTED,
@ -676,6 +690,9 @@ const Lbry = {
sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params), sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params),
sync_apply: (params = {}) => daemonCallWithResult('sync_apply', 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 to the sdk
connect: () => { connect: () => {
if (Lbry.connectPromise === null) { if (Lbry.connectPromise === null) {
@ -2761,6 +2778,74 @@ 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);
});
};
}
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: {
response: result
}
});
dispatch({
type: COMMENT_LIST_UPDATED,
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; }; 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 = {}; const reducers = {};
@ -3724,6 +3809,70 @@ function contentReducer(state = defaultState$6, action) {
return state; return state;
} }
//
// TODO change to handleActions()
// const commentsReducer = handleActions( {
const reducers$4 = {};
const defaultState$7 = {
byId: {},
commentsByUri: {},
isLoading: false
};
reducers$4[COMMENT_CREATE_STARTED] = (state, action) => Object.assign({}, state, {
isLoading: true
});
reducers$4[COMMENT_CREATE_FAILED] = (state, action) => {
// TODO: handle error.. what else?
return state;
};
reducers$4[COMMENT_CREATE_COMPLETED] = (state, action) => {
const { comments } = action.data;
return state;
};
reducers$4[COMMENT_LIST_UPDATED] = (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 Object.assign({}, state, {
byId
});
};
reducers$4[COMMENT_LIST_STARTED] = state => Object.assign({}, state, {
isLoading: true
});
reducers$4[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 Object.assign({}, state, {
byId,
commentsByUri,
isLoading: false
});
};
function commentReducer(state = defaultState$7, action) {
const handler = reducers$4[action.type];
if (handler) return handler(state, 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$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 tagsReducerBuilder = defaultState => handleActions({ const tagsReducerBuilder = defaultState => handleActions({
@ -3810,11 +3959,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))); const selectFollowedTags = reselect.createSelector(selectFollowedTagsList, followedTags => followedTags.map(tag => ({ name: tag })).sort((a, b) => a.name.localeCompare(b.name)));
@ -3844,6 +4018,7 @@ exports.TRANSACTIONS = transaction_types;
exports.batchActions = batchActions; exports.batchActions = batchActions;
exports.buildURI = buildURI; exports.buildURI = buildURI;
exports.claimsReducer = claimsReducer; exports.claimsReducer = claimsReducer;
exports.commentReducer = commentReducer;
exports.contentReducer = contentReducer; exports.contentReducer = contentReducer;
exports.convertToShareLink = convertToShareLink; exports.convertToShareLink = convertToShareLink;
exports.creditsToString = creditsToString; exports.creditsToString = creditsToString;
@ -3853,6 +4028,8 @@ exports.doBalanceSubscribe = doBalanceSubscribe;
exports.doBlurSearchInput = doBlurSearchInput; exports.doBlurSearchInput = doBlurSearchInput;
exports.doCheckAddressIsMine = doCheckAddressIsMine; exports.doCheckAddressIsMine = doCheckAddressIsMine;
exports.doClaimSearch = doClaimSearch; exports.doClaimSearch = doClaimSearch;
exports.doCommentCreate = doCommentCreate;
exports.doCommentList = doCommentList;
exports.doCreateChannel = doCreateChannel; exports.doCreateChannel = doCreateChannel;
exports.doDeletePurchasedUri = doDeletePurchasedUri; exports.doDeletePurchasedUri = doDeletePurchasedUri;
exports.doDeleteTag = doDeleteTag; exports.doDeleteTag = doDeleteTag;
@ -3906,6 +4083,7 @@ exports.makeSelectClaimIsNsfw = makeSelectClaimIsNsfw;
exports.makeSelectClaimIsPending = makeSelectClaimIsPending; exports.makeSelectClaimIsPending = makeSelectClaimIsPending;
exports.makeSelectClaimsInChannelForCurrentPageState = makeSelectClaimsInChannelForCurrentPageState; exports.makeSelectClaimsInChannelForCurrentPageState = makeSelectClaimsInChannelForCurrentPageState;
exports.makeSelectClaimsInChannelForPage = makeSelectClaimsInChannelForPage; exports.makeSelectClaimsInChannelForPage = makeSelectClaimsInChannelForPage;
exports.makeSelectCommentsForUri = makeSelectCommentsForUri;
exports.makeSelectContentPositionForUri = makeSelectContentPositionForUri; exports.makeSelectContentPositionForUri = makeSelectContentPositionForUri;
exports.makeSelectContentTypeForUri = makeSelectContentTypeForUri; exports.makeSelectContentTypeForUri = makeSelectContentTypeForUri;
exports.makeSelectCoverForUri = makeSelectCoverForUri; 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>, outputs: Array<ChannelClaim>,
}; };
declare type CommentCreateResponse = Comment;
declare type CommentListResponse = Array<Comment>;
declare type ChannelListResponse = Array<ChannelClaim>; declare type ChannelListResponse = Array<ChannelClaim>;
declare type FileListResponse = Array<FileListItem>; declare type FileListResponse = Array<FileListItem>;
@ -184,6 +187,9 @@ declare type LbryTypes = {
blob_delete: (params: {}) => Promise<string>, blob_delete: (params: {}) => Promise<string>,
blob_list: (params: {}) => Promise<BlobListResponse>, blob_list: (params: {}) => Promise<BlobListResponse>,
// Commenting
comment_list: (params: {}) => Promise<CommentListResponse>,
comment_create: (params: {}) => Promise<CommentCreateResponse>,
// Wallet utilities // Wallet utilities
account_balance: (params: {}) => Promise<string>, account_balance: (params: {}) => Promise<string>,
account_decrypt: (prams: {}) => Promise<boolean>, 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>, outputs: Array<ChannelClaim>,
}; };
declare type CommentCreateResponse = Comment;
declare type CommentListResponse = Array<Comment>;
declare type ChannelListResponse = Array<ChannelClaim>; declare type ChannelListResponse = Array<ChannelClaim>;
declare type FileListResponse = Array<FileListItem>; declare type FileListResponse = Array<FileListItem>;
@ -184,6 +187,9 @@ declare type LbryTypes = {
blob_delete: (params: {}) => Promise<string>, blob_delete: (params: {}) => Promise<string>,
blob_list: (params: {}) => Promise<BlobListResponse>, blob_list: (params: {}) => Promise<BlobListResponse>,
// Commenting
comment_list: (params: {}) => Promise<CommentListResponse>,
comment_create: (params: {}) => Promise<CommentCreateResponse>,
// Wallet utilities // Wallet utilities
account_balance: (params: {}) => Promise<string>, account_balance: (params: {}) => Promise<string>,
account_decrypt: (prams: {}) => Promise<boolean>, 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_COMPLETED = 'CLAIM_SEARCH_COMPLETED';
export const CLAIM_SEARCH_FAILED = 'CLAIM_SEARCH_FAILED'; 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_UPDATED = 'COMMENT_LIST_UPDATED';
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 // Files
export const FILE_LIST_STARTED = 'FILE_LIST_STARTED'; export const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
export const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED'; export const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED';

View file

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

View file

@ -100,6 +100,9 @@ const Lbry: LbryTypes = {
sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params), sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params),
sync_apply: (params = {}) => daemonCallWithResult('sync_apply', 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 to the sdk
connect: () => { connect: () => {
if (Lbry.connectPromise === null) { if (Lbry.connectPromise === null) {

View file

@ -0,0 +1,82 @@
// @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 => {
dispatch({
type: ACTIONS.COMMENT_LIST_COMPLETED,
data: {
comments: results,
claimId: claimId,
uri: uri,
},
});
})
.catch(error => {
console.log(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: {
response: result,
},
});
dispatch({
type: ACTIONS.COMMENT_LIST_UPDATED,
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,66 @@
// @flow
import * as ACTIONS from 'constants/action_types';
// TODO change to handleActions()
// const commentsReducer = handleActions( {
const reducers = {};
const defaultState: CommentsState = {
byId: {},
commentsByUri: {},
isLoading: false,
};
reducers[ACTIONS.COMMENT_CREATE_STARTED] = (state: CommentsState, action: any): CommentsState =>
Object.assign({}, state, {
isLoading: true,
});
reducers[ACTIONS.COMMENT_CREATE_FAILED] = (state: CommentsState, action: any): CommentsState => {
// TODO: handle error.. what else?
return state;
};
reducers[ACTIONS.COMMENT_CREATE_COMPLETED] = (state: CommentsState, action: any): CommentsState => {
const { comments }: any = action.data;
return state;
};
reducers[ACTIONS.COMMENT_LIST_UPDATED] = (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 Object.assign({}, state, {
byId,
});
};
reducers[ACTIONS.COMMENT_LIST_STARTED] = state =>
Object.assign({}, state, {
isLoading: true,
});
reducers[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 Object.assign({}, state, {
byId,
commentsByUri,
isLoading: false,
});
};
export function commentReducer(state: CommentsState = defaultState, action: any) {
const handler = reducers[action.type];
if (handler) return handler(state, action);
return state;
}

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];
}
);