add purchase_list

This commit is contained in:
Sean Yesmunt 2020-05-08 16:47:33 -04:00
parent 259317250a
commit 278e12dcbe
13 changed files with 421 additions and 34 deletions

171
dist/bundle.es.js vendored
View file

@ -149,6 +149,9 @@ const ADD_FILES_REFLECTING = 'ADD_FILES_REFLECTING';
const UPDATE_FILES_REFLECTING = 'UPDATE_FILES_REFLECTING';
const TOGGLE_CHECKING_REFLECTING = 'TOGGLE_CHECKING_REFLECTING';
const TOGGLE_CHECKING_PENDING = 'TOGGLE_CHECKING_PENDING';
const PURCHASE_LIST_STARTED = 'PURCHASE_LIST_STARTED';
const PURCHASE_LIST_COMPLETED = 'PURCHASE_LIST_COMPLETED';
const PURCHASE_LIST_FAILED = 'PURCHASE_LIST_FAILED';
// Comments
const COMMENT_LIST_STARTED = 'COMMENT_LIST_STARTED';
@ -429,6 +432,9 @@ var action_types = /*#__PURE__*/Object.freeze({
UPDATE_FILES_REFLECTING: UPDATE_FILES_REFLECTING,
TOGGLE_CHECKING_REFLECTING: TOGGLE_CHECKING_REFLECTING,
TOGGLE_CHECKING_PENDING: TOGGLE_CHECKING_PENDING,
PURCHASE_LIST_STARTED: PURCHASE_LIST_STARTED,
PURCHASE_LIST_COMPLETED: PURCHASE_LIST_COMPLETED,
PURCHASE_LIST_FAILED: PURCHASE_LIST_FAILED,
COMMENT_LIST_STARTED: COMMENT_LIST_STARTED,
COMMENT_LIST_COMPLETED: COMMENT_LIST_COMPLETED,
COMMENT_LIST_FAILED: COMMENT_LIST_FAILED,
@ -1090,6 +1096,7 @@ const Lbry = {
transaction_list: (params = {}) => daemonCallWithResult('transaction_list', params),
utxo_release: (params = {}) => daemonCallWithResult('utxo_release', params),
support_abandon: (params = {}) => daemonCallWithResult('support_abandon', params),
purchase_list: (params = {}) => daemonCallWithResult('purchase_list', params),
sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params),
sync_apply: (params = {}) => daemonCallWithResult('sync_apply', params),
@ -2136,7 +2143,21 @@ function createNormalizedClaimSearchKey(options) {
return query;
}
function filterClaims(claims, query) {
if (query) {
const queryMatchRegExp = new RegExp(query, 'i');
return claims.filter(claim => {
const { value } = claim;
return value.title && value.title.match(queryMatchRegExp) || claim.signing_channel && claim.signing_channel.name.match(queryMatchRegExp) || claim.name && claim.name.match(queryMatchRegExp);
});
}
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 || {});
@ -2277,6 +2298,30 @@ const makeSelectClaimIsMine = rawUri => {
});
};
const selectMyPurchases = reselect.createSelector(selectState$2, state => state.myPurchases);
const selectMyPurchasesCount = reselect.createSelector(selectState$2, state => state.myPurchasesPageTotalResults);
const selectIsFetchingMyPurchases = reselect.createSelector(selectState$2, state => state.fetchingMyPurchases);
const selectFetchingMyPurchasesError = reselect.createSelector(selectState$2, state => state.fetchingMyPurchasesError);
const makeSelectMyPurchasesForPage = (query, page = 1) => reselect.createSelector(selectMyPurchases, selectClaimsByUri, (myPurchases, claimsByUri) => {
if (!myPurchases) {
return undefined;
}
const fileInfos = myPurchases.map(uri => claimsByUri[uri]);
const matchingFileInfos = filterClaims(fileInfos, query);
const start = (Number(page) - 1) * Number(PAGE_SIZE);
const end = Number(page) * Number(PAGE_SIZE);
return matchingFileInfos && matchingFileInfos.length ? matchingFileInfos.slice(start, end).map(fileInfo => fileInfo.canonical_url || fileInfo.permanent_url) : [];
});
const makeSelectClaimWasPurchased = uri => reselect.createSelector(makeSelectClaimForUri(uri), claim => {
return claim && claim.purchase_receipt !== undefined;
});
const selectAllFetchingChannelClaims = reselect.createSelector(selectState$2, state => state.fetchingChannelClaims || {});
const makeSelectFetchingChannelClaims = uri => reselect.createSelector(selectAllFetchingChannelClaims, fetching => fetching && fetching[uri]);
@ -2540,7 +2585,7 @@ const makeSelectCanonicalUrlForUri = uri => reselect.createSelector(makeSelectCl
const makeSelectPermanentUrlForUri = uri => reselect.createSelector(makeSelectClaimForUri(uri), claim => claim && claim.permanent_url);
const makeSelectSupportsForUri = uri => reselect.createSelector(selectSupportsByOutpoint, makeSelectClaimForUri(uri), (byOutpoint, claim) => {
if (!claim || !claim.is_mine) {
if (!claim || !claim.is_my_output) {
return null;
}
@ -3180,7 +3225,9 @@ function doResolveUris(uris, returnCachedClaims = false) {
return;
}
const options = {};
const options = {
include_purchase_receipt: true
};
if (urisToResolve.length === 1) {
options.include_is_my_output = true;
@ -3427,7 +3474,8 @@ function doFetchClaimsByChannel(uri, page = 1) {
valid_channel_signature: true,
page: page || 1,
order_by: ['release_time'],
include_is_my_output: true
include_is_my_output: true,
include_purchase_receipt: true
}).then(result => {
const { items: claims, total_items: claimsInChannel, page: returnedPage } = result;
@ -3630,7 +3678,9 @@ function doClaimSearch(options = {
});
};
lbryProxy.claim_search(options).then(success, failure);
lbryProxy.claim_search(_extends$5({}, options, {
include_purchase_receipt: true
})).then(success, failure);
};
}
@ -3700,6 +3750,38 @@ function doClearRepostError() {
};
}
function doPurchaseList(page = 1, pageSize = 99999) {
return dispatch => {
dispatch({
type: PURCHASE_LIST_STARTED
});
const success = result => {
return dispatch({
type: PURCHASE_LIST_COMPLETED,
data: {
result
}
});
};
const failure = error => {
dispatch({
type: PURCHASE_LIST_FAILED,
data: {
error: error.message
}
});
};
lbryProxy.purchase_list({
page: page,
page_size: pageSize,
resolve: true
}).then(success, failure);
};
}
const selectState$3 = state => state.fileInfo || {};
const selectFileInfosByOutpoint = reselect.createSelector(selectState$3, state => state.byOutpoint || {});
@ -3820,6 +3902,7 @@ function filterFileInfos(fileInfos, query) {
const queryMatchRegExp = new RegExp(query, 'i');
return fileInfos.filter(fileInfo => {
const { metadata } = fileInfo;
return metadata.title && metadata.title.match(queryMatchRegExp) || fileInfo.channel_name && fileInfo.channel_name.match(queryMatchRegExp) || fileInfo.claim_name && fileInfo.claim_name.match(queryMatchRegExp);
});
}
@ -5021,6 +5104,8 @@ const doToggleBlockChannel = uri => ({
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; };
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; }
const reducers = {};
const defaultState = {
byId: {},
@ -5029,10 +5114,13 @@ const defaultState = {
channelClaimCounts: {},
fetchingChannelClaims: {},
resolvingUris: [],
// This should not be a Set
// Storing sets in reducers can cause issues
myChannelClaims: undefined,
myClaims: undefined,
myPurchases: undefined,
myPurchasesPageNumber: undefined,
myPurchasesPageTotalResults: undefined,
fetchingMyPurchases: false,
fetchingMyPurchasesError: undefined,
fetchingMyChannels: false,
abandoningById: {},
pendingById: {},
@ -5053,6 +5141,7 @@ const defaultState = {
myClaimsPageNumber: undefined,
myClaimsPageTotalResults: undefined,
isFetchingClaimListMine: false,
isFetchingMyPurchases: false,
isCheckingNameForPublish: false,
checkingPending: false,
checkingReflecting: false
@ -5150,13 +5239,13 @@ reducers[FETCH_CLAIM_LIST_MINE_COMPLETED] = (state, action) => {
const byUri = Object.assign({}, state.claimsByUri);
const pendingById = Object.assign({}, state.pendingById);
let myClaimIds = new Set(state.myClaims);
let urlPage = [];
let urlsForCurrentPage = [];
claims.forEach(claim => {
const uri = buildURI({ streamName: claim.name, streamClaimId: claim.claim_id });
const { claim_id: claimId } = claim;
if (claim.type && claim.type.match(/claim|update/)) {
urlPage.push(uri);
urlsForCurrentPage.push(uri);
if (claim.confirmations < 1) {
pendingById[claimId] = claim;
delete byId[claimId];
@ -5188,7 +5277,7 @@ reducers[FETCH_CLAIM_LIST_MINE_COMPLETED] = (state, action) => {
byId,
claimsByUri: byUri,
pendingById,
myClaimsPageResults: urlPage,
myClaimsPageResults: urlsForCurrentPage,
myClaimsPageNumber: page,
myClaimsPageTotalResults: totalItems
});
@ -5325,6 +5414,7 @@ reducers[UPDATE_PENDING_CLAIMS] = (state, action) => {
const pendingById = Object.assign({}, state.pendingById);
let myClaimIds = new Set(state.myClaims);
// $FlowFixMe
claims.forEach(claim => {
const uri = buildURI({ streamName: claim.name, streamClaimId: claim.claim_id });
const { claim_id: claimId } = claim;
@ -5570,6 +5660,58 @@ reducers[TOGGLE_CHECKING_PENDING] = (state, action) => {
}));
};
reducers[PURCHASE_LIST_STARTED] = state => {
return _extends$9({}, state, {
fetchingMyPurchases: true,
fetchingMyPurchasesError: null
});
};
reducers[PURCHASE_LIST_COMPLETED] = (state, action) => {
const { result } = action.data;
const page = result.page;
const totalItems = result.total_items;
let byId = Object.assign({}, state.byId);
let byUri = Object.assign({}, state.claimsByUri);
let urlsForCurrentPage = [];
result.items.forEach(item => {
if (!item.claim) {
// Abandoned claim
return;
}
const { claim } = item,
purchaseInfo = _objectWithoutProperties$3(item, ['claim']);
claim.purchase_receipt = purchaseInfo;
const claimId = claim.claim_id;
const uri = claim.canonical_url;
byId[claimId] = claim;
byUri[uri] = claimId;
urlsForCurrentPage.push(uri);
});
return Object.assign({}, state, {
byId,
claimsByUri: byUri,
myPurchases: urlsForCurrentPage,
myPurchasesPageNumber: page,
myPurchasesPageTotalResults: totalItems,
fetchingMyPurchases: false
});
};
reducers[PURCHASE_LIST_FAILED] = (state, action) => {
const { error } = action.data;
return _extends$9({}, state, {
fetchingMyPurchases: false,
fetchingMyPurchasesError: error
});
};
function claimsReducer(state = defaultState, action) {
const handler = reducers[action.type];
if (handler) return handler(state, action);
@ -6061,7 +6203,7 @@ const notificationsReducer = handleActions({
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; }
function _objectWithoutProperties$4(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; }
const defaultState$6 = {
editingURI: undefined,
@ -6118,7 +6260,7 @@ const publishReducer = handleActions({
publishSuccess: true
}),
[DO_PREPARE_EDIT]: (state, action) => {
const publishData = _objectWithoutProperties$3(action.data, []);
const publishData = _objectWithoutProperties$4(action.data, []);
const { channel, name, uri } = publishData;
// The short uri is what is presented to the user
@ -6879,6 +7021,7 @@ exports.doPreferenceGet = doPreferenceGet;
exports.doPreferenceSet = doPreferenceSet;
exports.doPrepareEdit = doPrepareEdit;
exports.doPublish = doPublish;
exports.doPurchaseList = doPurchaseList;
exports.doPurchaseUri = doPurchaseUri;
exports.doRepost = doRepost;
exports.doResetThumbnailStatus = doResetThumbnailStatus;
@ -6924,6 +7067,7 @@ exports.makeSelectClaimForUri = makeSelectClaimForUri;
exports.makeSelectClaimIsMine = makeSelectClaimIsMine;
exports.makeSelectClaimIsNsfw = makeSelectClaimIsNsfw;
exports.makeSelectClaimIsPending = makeSelectClaimIsPending;
exports.makeSelectClaimWasPurchased = makeSelectClaimWasPurchased;
exports.makeSelectClaimsInChannelForCurrentPageState = makeSelectClaimsInChannelForCurrentPageState;
exports.makeSelectClaimsInChannelForPage = makeSelectClaimsInChannelForPage;
exports.makeSelectCommentsForUri = makeSelectCommentsForUri;
@ -6946,6 +7090,7 @@ exports.makeSelectLoadingForUri = makeSelectLoadingForUri;
exports.makeSelectMediaTypeForUri = makeSelectMediaTypeForUri;
exports.makeSelectMetadataForUri = makeSelectMetadataForUri;
exports.makeSelectMetadataItemForUri = makeSelectMetadataItemForUri;
exports.makeSelectMyPurchasesForPage = makeSelectMyPurchasesForPage;
exports.makeSelectMyStreamUrlsForPage = makeSelectMyStreamUrlsForPage;
exports.makeSelectNsfwCountForChannel = makeSelectNsfwCountForChannel;
exports.makeSelectNsfwCountFromUris = makeSelectNsfwCountFromUris;
@ -7018,6 +7163,7 @@ exports.selectFetchingClaimSearch = selectFetchingClaimSearch;
exports.selectFetchingClaimSearchByQuery = selectFetchingClaimSearchByQuery;
exports.selectFetchingMyChannels = selectFetchingMyChannels;
exports.selectFetchingMyClaimsPageError = selectFetchingMyClaimsPageError;
exports.selectFetchingMyPurchasesError = selectFetchingMyPurchasesError;
exports.selectFetchingTxosError = selectFetchingTxosError;
exports.selectFileInfosByOutpoint = selectFileInfosByOutpoint;
exports.selectFileInfosDownloaded = selectFileInfosDownloaded;
@ -7032,6 +7178,7 @@ exports.selectHasTransactions = selectHasTransactions;
exports.selectIsFetchingClaimListMine = selectIsFetchingClaimListMine;
exports.selectIsFetchingFileList = selectIsFetchingFileList;
exports.selectIsFetchingFileListDownloadedOrPublished = selectIsFetchingFileListDownloadedOrPublished;
exports.selectIsFetchingMyPurchases = selectIsFetchingMyPurchases;
exports.selectIsFetchingTransactions = selectIsFetchingTransactions;
exports.selectIsFetchingTxos = selectIsFetchingTxos;
exports.selectIsResolvingPublishUris = selectIsResolvingPublishUris;
@ -7051,6 +7198,8 @@ exports.selectMyClaimsPageItemCount = selectMyClaimsPageItemCount;
exports.selectMyClaimsPageNumber = selectMyClaimsPageNumber;
exports.selectMyClaimsRaw = selectMyClaimsRaw;
exports.selectMyClaimsWithoutChannels = selectMyClaimsWithoutChannels;
exports.selectMyPurchases = selectMyPurchases;
exports.selectMyPurchasesCount = selectMyPurchasesCount;
exports.selectMyStreamUrlsCount = selectMyStreamUrlsCount;
exports.selectPendingById = selectPendingById;
exports.selectPendingClaims = selectPendingClaims;

View file

@ -3,12 +3,10 @@
declare type Claim = StreamClaim | ChannelClaim;
declare type ChannelClaim = GenericClaim & {
is_channel_signature_valid?: boolean, // we may have signed channels in the future
value: ChannelMetadata,
};
declare type StreamClaim = GenericClaim & {
is_channel_signature_valid?: boolean,
value: StreamMetadata,
};
@ -23,7 +21,8 @@ declare type GenericClaim = {
decoded_claim: boolean, // Not available currently https://github.com/lbryio/lbry/issues/2044
timestamp?: number, // date of last transaction
height: number, // block height the tx was confirmed
is_mine: boolean,
is_channel_signature_valid?: boolean,
is_my_output: true,
name: string,
normalized_name: string, // `name` normalized via unicode NFD spec,
nout: number, // index number for an output of a tx
@ -34,6 +33,7 @@ declare type GenericClaim = {
value_type: 'stream' | 'channel',
signing_channel?: ChannelClaim,
repost_channel_url?: string,
purchase_receipt?: PurchaseReceipt,
meta: {
activation_height: number,
claims_in_channel?: number,
@ -121,3 +121,15 @@ declare type Fee = {
currency: string,
address: string,
};
declare type PurchaseReceipt = {
address: string,
amount: string,
claim_id: string,
confirmations: number,
height: number,
nout: number,
timestamp: number,
txid: string,
type: 'purchase',
};

View file

@ -214,6 +214,22 @@ declare type StreamRepostOptions = {
declare type StreamRepostResponse = GenericTxResponse;
declare type PurchaseListResponse = {
items: Array<PurchaseReceipt & { claim: StreamClaim }>,
page: number,
page_size: number,
total_items: number,
total_pages: number,
};
declare type PurchaseListOptions = {
page: number,
page_size: number,
resolve: boolean,
claim_id?: string,
channel_id?: string,
};
//
// Types used in the generic Lbry object that is exported
//
@ -253,6 +269,7 @@ declare type LbryTypes = {
support_list: (params: {}) => Promise<SupportListResponse>,
support_abandon: (params: {}) => Promise<SupportAbandonResponse>,
stream_repost: (params: StreamRepostOptions) => Promise<StreamRepostResponse>,
purchase_list: (params: PurchaseListOptions) => Promise<PurchaseListResponse>,
// File fetching and manipulation
file_list: (params: {}) => Promise<FileListResponse>,

18
flow-typed/Claim.js vendored
View file

@ -3,12 +3,10 @@
declare type Claim = StreamClaim | ChannelClaim;
declare type ChannelClaim = GenericClaim & {
is_channel_signature_valid?: boolean, // we may have signed channels in the future
value: ChannelMetadata,
};
declare type StreamClaim = GenericClaim & {
is_channel_signature_valid?: boolean,
value: StreamMetadata,
};
@ -23,7 +21,8 @@ declare type GenericClaim = {
decoded_claim: boolean, // Not available currently https://github.com/lbryio/lbry/issues/2044
timestamp?: number, // date of last transaction
height: number, // block height the tx was confirmed
is_mine: boolean,
is_channel_signature_valid?: boolean,
is_my_output: true,
name: string,
normalized_name: string, // `name` normalized via unicode NFD spec,
nout: number, // index number for an output of a tx
@ -34,6 +33,7 @@ declare type GenericClaim = {
value_type: 'stream' | 'channel',
signing_channel?: ChannelClaim,
repost_channel_url?: string,
purchase_receipt?: PurchaseReceipt,
meta: {
activation_height: number,
claims_in_channel?: number,
@ -121,3 +121,15 @@ declare type Fee = {
currency: string,
address: string,
};
declare type PurchaseReceipt = {
address: string,
amount: string,
claim_id: string,
confirmations: number,
height: number,
nout: number,
timestamp: number,
txid: string,
type: 'purchase',
};

17
flow-typed/Lbry.js vendored
View file

@ -214,6 +214,22 @@ declare type StreamRepostOptions = {
declare type StreamRepostResponse = GenericTxResponse;
declare type PurchaseListResponse = {
items: Array<PurchaseReceipt & { claim: StreamClaim }>,
page: number,
page_size: number,
total_items: number,
total_pages: number,
};
declare type PurchaseListOptions = {
page: number,
page_size: number,
resolve: boolean,
claim_id?: string,
channel_id?: string,
};
//
// Types used in the generic Lbry object that is exported
//
@ -253,6 +269,7 @@ declare type LbryTypes = {
support_list: (params: {}) => Promise<SupportListResponse>,
support_abandon: (params: {}) => Promise<SupportAbandonResponse>,
stream_repost: (params: StreamRepostOptions) => Promise<StreamRepostResponse>,
purchase_list: (params: PurchaseListOptions) => Promise<PurchaseListResponse>,
// File fetching and manipulation
file_list: (params: {}) => Promise<FileListResponse>,

View file

@ -126,6 +126,9 @@ export const ADD_FILES_REFLECTING = 'ADD_FILES_REFLECTING';
export const UPDATE_FILES_REFLECTING = 'UPDATE_FILES_REFLECTING';
export const TOGGLE_CHECKING_REFLECTING = 'TOGGLE_CHECKING_REFLECTING';
export const TOGGLE_CHECKING_PENDING = 'TOGGLE_CHECKING_PENDING';
export const PURCHASE_LIST_STARTED = 'PURCHASE_LIST_STARTED';
export const PURCHASE_LIST_COMPLETED = 'PURCHASE_LIST_COMPLETED';
export const PURCHASE_LIST_FAILED = 'PURCHASE_LIST_FAILED';
// Comments
export const COMMENT_LIST_STARTED = 'COMMENT_LIST_STARTED';

View file

@ -75,6 +75,7 @@ export {
doRepost,
doClearRepostError,
doCheckPublishNameAvailability,
doPurchaseList,
} from 'redux/actions/claims';
export { doDeletePurchasedUri, doPurchaseUri, doFileGet } from 'redux/actions/file';
@ -213,6 +214,8 @@ export {
makeSelectCanonicalUrlForUri,
makeSelectPermanentUrlForUri,
makeSelectSupportsForUri,
makeSelectMyPurchasesForPage,
makeSelectClaimWasPurchased,
selectPendingById,
selectReflectingById,
selectClaimsById,
@ -253,6 +256,10 @@ export {
selectMyClaimsPageNumber,
selectMyClaimsPageItemCount,
selectFetchingMyClaimsPageError,
selectMyPurchases,
selectIsFetchingMyPurchases,
selectFetchingMyPurchasesError,
selectMyPurchasesCount,
} from 'redux/selectors/claims';
export { makeSelectCommentsForUri } from 'redux/selectors/comments';

View file

@ -111,6 +111,7 @@ const Lbry: LbryTypes = {
transaction_list: (params = {}) => daemonCallWithResult('transaction_list', params),
utxo_release: (params = {}) => daemonCallWithResult('utxo_release', params),
support_abandon: (params = {}) => daemonCallWithResult('support_abandon', params),
purchase_list: (params = {}) => daemonCallWithResult('purchase_list', params),
sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params),
sync_apply: (params = {}) => daemonCallWithResult('sync_apply', params),

View file

@ -35,7 +35,9 @@ export function doResolveUris(uris: Array<string>, returnCachedClaims: boolean =
return;
}
const options: { include_is_my_output?: boolean } = {};
const options: { include_is_my_output?: boolean, include_purchase_receipt: boolean } = {
include_purchase_receipt: true,
};
if (urisToResolve.length === 1) {
options.include_is_my_output = true;
@ -318,6 +320,7 @@ export function doFetchClaimsByChannel(uri: string, page: number = 1) {
page: page || 1,
order_by: ['release_time'],
include_is_my_output: true,
include_purchase_receipt: true,
}).then((result: ClaimSearchResponse) => {
const { items: claims, total_items: claimsInChannel, page: returnedPage } = result;
@ -554,7 +557,10 @@ export function doClaimSearch(
});
};
Lbry.claim_search(options).then(success, failure);
Lbry.claim_search({
...options,
include_purchase_receipt: true,
}).then(success, failure);
};
}
@ -623,3 +629,35 @@ export function doClearRepostError() {
type: ACTIONS.CLEAR_REPOST_ERROR,
};
}
export function doPurchaseList(page: number = 1, pageSize: number = 99999) {
return (dispatch: Dispatch) => {
dispatch({
type: ACTIONS.PURCHASE_LIST_STARTED,
});
const success = (result: PurchaseListResponse) => {
return dispatch({
type: ACTIONS.PURCHASE_LIST_COMPLETED,
data: {
result,
},
});
};
const failure = error => {
dispatch({
type: ACTIONS.PURCHASE_LIST_FAILED,
data: {
error: error.message,
},
});
};
Lbry.purchase_list({
page: page,
page_size: pageSize,
resolve: true,
}).then(success, failure);
};
}

View file

@ -25,6 +25,11 @@ type State = {
fetchingChannelClaims: { [string]: number },
fetchingMyChannels: boolean,
fetchingClaimSearchByQuery: { [string]: boolean },
myPurchases: ?Array<string>,
myPurchasesPageNumber: ?number,
myPurchasesPageTotalResults: ?number,
fetchingMyPurchases: boolean,
fetchingMyPurchasesError: ?string,
claimSearchByQuery: { [string]: Array<string> },
claimSearchByQueryLastPageReached: { [string]: Array<boolean> },
creatingChannel: boolean,
@ -59,10 +64,13 @@ const defaultState = {
channelClaimCounts: {},
fetchingChannelClaims: {},
resolvingUris: [],
// This should not be a Set
// Storing sets in reducers can cause issues
myChannelClaims: undefined,
myClaims: undefined,
myPurchases: undefined,
myPurchasesPageNumber: undefined,
myPurchasesPageTotalResults: undefined,
fetchingMyPurchases: false,
fetchingMyPurchasesError: undefined,
fetchingMyChannels: false,
abandoningById: {},
pendingById: {},
@ -83,6 +91,7 @@ const defaultState = {
myClaimsPageNumber: undefined,
myClaimsPageTotalResults: undefined,
isFetchingClaimListMine: false,
isFetchingMyPurchases: false,
isCheckingNameForPublish: false,
checkingPending: false,
checkingReflecting: false,
@ -189,13 +198,13 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any):
const byUri = Object.assign({}, state.claimsByUri);
const pendingById: { [string]: Claim } = Object.assign({}, state.pendingById);
let myClaimIds = new Set(state.myClaims);
let urlPage = [];
let urlsForCurrentPage = [];
claims.forEach((claim: Claim) => {
const uri = buildURI({ streamName: claim.name, streamClaimId: claim.claim_id });
const { claim_id: claimId } = claim;
if (claim.type && claim.type.match(/claim|update/)) {
urlPage.push(uri);
urlsForCurrentPage.push(uri);
if (claim.confirmations < 1) {
pendingById[claimId] = claim;
delete byId[claimId];
@ -228,7 +237,7 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any):
byId,
claimsByUri: byUri,
pendingById,
myClaimsPageResults: urlPage,
myClaimsPageResults: urlsForCurrentPage,
myClaimsPageNumber: page,
myClaimsPageTotalResults: totalItems,
});
@ -374,6 +383,7 @@ reducers[ACTIONS.UPDATE_PENDING_CLAIMS] = (state: State, action: any): State =>
const pendingById: { [string]: Claim } = Object.assign({}, state.pendingById);
let myClaimIds = new Set(state.myClaims);
// $FlowFixMe
claims.forEach((claim: Claim) => {
const uri = buildURI({ streamName: claim.name, streamClaimId: claim.claim_id });
const { claim_id: claimId } = claim;
@ -637,6 +647,59 @@ reducers[ACTIONS.TOGGLE_CHECKING_PENDING] = (state: State, action): State => {
});
};
reducers[ACTIONS.PURCHASE_LIST_STARTED] = (state: State): State => {
return {
...state,
fetchingMyPurchases: true,
fetchingMyPurchasesError: null,
};
};
reducers[ACTIONS.PURCHASE_LIST_COMPLETED] = (state: State, action: any): State => {
const { result }: { result: PurchaseListResponse, resolve: boolean } = action.data;
const page = result.page;
const totalItems = result.total_items;
let byId = Object.assign({}, state.byId);
let byUri = Object.assign({}, state.claimsByUri);
let urlsForCurrentPage = [];
result.items.forEach(item => {
if (!item.claim) {
// Abandoned claim
return;
}
const { claim, ...purchaseInfo } = item;
claim.purchase_receipt = purchaseInfo;
const claimId = claim.claim_id;
const uri = claim.canonical_url;
byId[claimId] = claim;
byUri[uri] = claimId;
urlsForCurrentPage.push(uri);
});
return Object.assign({}, state, {
byId,
claimsByUri: byUri,
myPurchases: urlsForCurrentPage,
myPurchasesPageNumber: page,
myPurchasesPageTotalResults: totalItems,
fetchingMyPurchases: false,
});
};
reducers[ACTIONS.PURCHASE_LIST_FAILED] = (state: State, action: any): State => {
const { error } = action.data;
return {
...state,
fetchingMyPurchases: false,
fetchingMyPurchasesError: error,
};
};
export function claimsReducer(state: State = defaultState, action: any) {
const handler = reducers[action.type];
if (handler) return handler(state, action);

View file

@ -6,9 +6,10 @@ import {
} from 'redux/selectors/search';
import { selectSupportsByOutpoint } from 'redux/selectors/wallet';
import { createSelector } from 'reselect';
import { isClaimNsfw, createNormalizedClaimSearchKey } from 'util/claim';
import { isClaimNsfw, createNormalizedClaimSearchKey, filterClaims } from 'util/claim';
import { getSearchQueryString } from 'util/query-params';
import { PAGE_SIZE } from 'constants/claim';
const selectState = state => state.claims || {};
export const selectClaimsById = createSelector(
@ -225,6 +226,55 @@ export const makeSelectClaimIsMine = (rawUri: string) => {
);
};
export const selectMyPurchases = createSelector(
selectState,
state => state.myPurchases
);
export const selectMyPurchasesCount = createSelector(
selectState,
state => state.myPurchasesPageTotalResults
);
export const selectIsFetchingMyPurchases = createSelector(
selectState,
state => state.fetchingMyPurchases
);
export const selectFetchingMyPurchasesError = createSelector(
selectState,
state => state.fetchingMyPurchasesError
);
export const makeSelectMyPurchasesForPage = (query: ?string, page: number = 1) =>
createSelector(
selectMyPurchases,
selectClaimsByUri,
(myPurchases: Array<string>, claimsByUri: { [string]: Claim }) => {
if (!myPurchases) {
return undefined;
}
const fileInfos = myPurchases.map(uri => claimsByUri[uri]);
const matchingFileInfos = filterClaims(fileInfos, query);
const start = (Number(page) - 1) * Number(PAGE_SIZE);
const end = Number(page) * Number(PAGE_SIZE);
return matchingFileInfos && matchingFileInfos.length
? matchingFileInfos
.slice(start, end)
.map(fileInfo => fileInfo.canonical_url || fileInfo.permanent_url)
: [];
}
);
export const makeSelectClaimWasPurchased = (uri: string) =>
createSelector(
makeSelectClaimForUri(uri),
claim => {
return claim && claim.purchase_receipt !== undefined;
}
);
export const selectAllFetchingChannelClaims = createSelector(
selectState,
state => state.fetchingChannelClaims || {}
@ -694,7 +744,7 @@ export const makeSelectSupportsForUri = (uri: string) =>
selectSupportsByOutpoint,
makeSelectClaimForUri(uri),
(byOutpoint, claim: ?StreamClaim) => {
if (!claim || !claim.is_mine) {
if (!claim || !claim.is_my_output) {
return null;
}

View file

@ -212,6 +212,7 @@ function filterFileInfos(fileInfos, query) {
const queryMatchRegExp = new RegExp(query, 'i');
return fileInfos.filter(fileInfo => {
const { metadata } = fileInfo;
return (
(metadata.title && metadata.title.match(queryMatchRegExp)) ||
(fileInfo.channel_name && fileInfo.channel_name.match(queryMatchRegExp)) ||

View file

@ -51,3 +51,20 @@ export function concatClaims(
return claims;
}
export function filterClaims(claims: Array<Claim>, query: ?string): Array<Claim> {
if (query) {
const queryMatchRegExp = new RegExp(query, 'i');
return claims.filter(claim => {
const { value } = claim;
return (
(value.title && value.title.match(queryMatchRegExp)) ||
(claim.signing_channel && claim.signing_channel.name.match(queryMatchRegExp)) ||
(claim.name && claim.name.match(queryMatchRegExp))
);
});
}
return claims;
}