Compare commits

..

3 commits

Author SHA1 Message Date
jessop 8a737de116 restore to enable_sync in client settings 2020-09-17 21:03:59 -04:00
jessop f287775d62 remove enable_sync from sync list 2020-09-17 18:07:40 -04:00
jessop 0d21b03d16 change alt preference key to local 2020-09-16 09:56:24 -04:00
50 changed files with 1326 additions and 8790 deletions

View file

@ -1,6 +1,5 @@
[ignore] [ignore]
[include] [include]
[libs] [libs]

View file

@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2017-2021 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 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, "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish,

2633
dist/bundle.es.js vendored

File diff suppressed because one or more lines are too long

View file

@ -1,15 +1,11 @@
// @flow // @flow
declare type Claim = StreamClaim | ChannelClaim | CollectionClaim; declare type Claim = StreamClaim | ChannelClaim;
declare type ChannelClaim = GenericClaim & { declare type ChannelClaim = GenericClaim & {
value: ChannelMetadata, value: ChannelMetadata,
}; };
declare type CollectionClaim = GenericClaim & {
value: CollectionMetadata,
};
declare type StreamClaim = GenericClaim & { declare type StreamClaim = GenericClaim & {
value: StreamMetadata, value: StreamMetadata,
}; };
@ -34,12 +30,9 @@ declare type GenericClaim = {
short_url: string, // permanent_url with short id, no channel short_url: string, // permanent_url with short id, no channel
txid: string, // unique tx id txid: string, // unique tx id
type: 'claim' | 'update' | 'support', type: 'claim' | 'update' | 'support',
value_type: 'stream' | 'channel' | 'collection', value_type: 'stream' | 'channel',
signing_channel?: ChannelClaim, signing_channel?: ChannelClaim,
reposted_claim?: GenericClaim,
repost_channel_url?: string, repost_channel_url?: string,
repost_url?: string,
repost_bid_amount?: string,
purchase_receipt?: PurchaseReceipt, purchase_receipt?: PurchaseReceipt,
meta: { meta: {
activation_height: number, activation_height: number,
@ -78,10 +71,6 @@ declare type ChannelMetadata = GenericMetadata & {
featured?: Array<string>, featured?: Array<string>,
}; };
declare type CollectionMetadata = GenericMetadata & {
claims: Array<string>,
}
declare type StreamMetadata = GenericMetadata & { declare type StreamMetadata = GenericMetadata & {
license?: string, // License "title" ex: Creative Commons, Custom copyright license?: string, // License "title" ex: Creative Commons, Custom copyright
license_url?: string, // Link to full license license_url?: string, // Link to full license
@ -144,71 +133,3 @@ declare type PurchaseReceipt = {
txid: string, txid: string,
type: 'purchase', type: 'purchase',
}; };
declare type ClaimActionResolveInfo = {
[string]: {
stream: ?StreamClaim,
channel: ?ChannelClaim,
claimsInChannel: ?number,
collection: ?CollectionClaim,
},
}
declare type ChannelUpdateParams = {
claim_id: string,
bid?: string,
title?: string,
cover_url?: string,
thumbnail_url?: string,
description?: string,
website_url?: string,
email?: string,
tags?: Array<string>,
replace?: boolean,
languages?: Array<string>,
locations?: Array<string>,
blocking?: boolean,
}
declare type ChannelPublishParams = {
name: string,
bid: string,
blocking?: true,
title?: string,
cover_url?: string,
thumbnail_url?: string,
description?: string,
website_url?: string,
email?: string,
tags?: Array<string>,
languages?: Array<string>,
}
declare type CollectionUpdateParams = {
claim_id: string,
claim_ids?: Array<string>,
bid?: string,
title?: string,
cover_url?: string,
thumbnail_url?: string,
description?: string,
website_url?: string,
email?: string,
tags?: Array<string>,
replace?: boolean,
languages?: Array<string>,
locations?: Array<string>,
blocking?: boolean,
}
declare type CollectionPublishParams = {
name: string,
bid: string,
claim_ids: Array<string>,
blocking?: true,
title?: string,
thumbnail_url?: string,
description?: string,
tags?: Array<string>,
languages?: Array<string>,
}

View file

@ -1,29 +0,0 @@
declare type CoinSwapInfo = {
chargeCode: string,
coins: Array<string>,
sendAddresses: { [string]: string},
sendAmounts: { [string]: any },
lbcAmount: number,
status?: {
status: string,
receiptCurrency: string,
receiptTxid: string,
lbcTxid: string,
},
}
declare type CoinSwapState = {
coinSwaps: Array<CoinSwapInfo>,
};
declare type CoinSwapAddAction = {
type: string,
data: CoinSwapInfo,
};
declare type CoinSwapRemoveAction = {
type: string,
data: {
chargeCode: string,
},
};

View file

@ -1,34 +0,0 @@
declare type Collection = {
id: string,
items: Array<?string>,
name: string,
type: string,
updatedAt: number,
totalItems?: number,
sourceId?: string, // if copied, claimId of original collection
};
declare type CollectionState = {
unpublished: CollectionGroup,
resolved: CollectionGroup,
pending: CollectionGroup,
edited: CollectionGroup,
builtin: CollectionGroup,
saved: Array<string>,
isResolvingCollectionById: { [string]: boolean },
error?: string | null,
};
declare type CollectionGroup = {
[string]: Collection,
}
declare type CollectionEditParams = {
claims?: Array<Claim>,
remove?: boolean,
claimIds?: Array<string>,
replace?: boolean,
order?: { from: number, to: number },
type?: string,
name?: string,
}

View file

@ -7,6 +7,10 @@ declare type StatusResponse = {
download_progress: number, download_progress: number,
downloading_headers: boolean, downloading_headers: boolean,
}, },
connection_status: {
code: string,
message: string,
},
dht: { dht: {
node_id: string, node_id: string,
peers_in_routing_table: number, peers_in_routing_table: number,
@ -41,7 +45,6 @@ declare type StatusResponse = {
redirects: {}, redirects: {},
}, },
wallet: ?{ wallet: ?{
connected: string,
best_blockhash: string, best_blockhash: string,
blocks: number, blocks: number,
blocks_behind: number, blocks_behind: number,
@ -75,7 +78,7 @@ declare type BalanceResponse = {
declare type ResolveResponse = { declare type ResolveResponse = {
// Keys are the url(s) passed to resolve // Keys are the url(s) passed to resolve
[string]: { error?: {}, stream?: StreamClaim, channel?: ChannelClaim, collection?: CollectionClaim, claimsInChannel?: number }, [string]: { error?: {}, stream?: StreamClaim, channel?: ChannelClaim, claimsInChannel?: number },
}; };
declare type GetResponse = FileListItem & { error?: string }; declare type GetResponse = FileListItem & { error?: string };
@ -124,22 +127,12 @@ declare type ChannelUpdateResponse = GenericTxResponse & {
declare type CommentCreateResponse = Comment; declare type CommentCreateResponse = Comment;
declare type CommentUpdateResponse = Comment; declare type CommentUpdateResponse = Comment;
declare type MyReactions = { declare type CommentListResponse = {
// Keys are the commentId items: Array<Comment>,
[string]: Array<string>, page: number,
}; page_size: number,
total_items: number,
declare type OthersReactions = { total_pages: number,
// Keys are the commentId
[string]: {
// Keys are the reaction_type, e.g. 'like'
[string]: number,
},
};
declare type CommentReactListResponse = {
my_reactions: Array<MyReactions>,
others_reactions: Array<OthersReactions>,
}; };
declare type CommentHideResponse = { declare type CommentHideResponse = {
@ -147,11 +140,6 @@ declare type CommentHideResponse = {
[string]: { hidden: boolean }, [string]: { hidden: boolean },
}; };
declare type CommentPinResponse = {
// keyed by the CommentIds entered
items: Comment,
};
declare type CommentAbandonResponse = { declare type CommentAbandonResponse = {
// keyed by the CommentId given // keyed by the CommentId given
abandoned: boolean, abandoned: boolean,
@ -165,42 +153,6 @@ declare type ChannelListResponse = {
total_pages: number, total_pages: number,
}; };
declare type ChannelSignResponse = {
signature: string,
signing_ts: string,
};
declare type CollectionCreateResponse = {
outputs: Array<Claim>,
page: number,
page_size: number,
total_items: number,
total_pages: number,
}
declare type CollectionListResponse = {
items: Array<Claim>,
page: number,
page_size: number,
total_items: number,
total_pages: number,
};
declare type CollectionResolveResponse = {
items: Array<Claim>,
total_items: number,
};
declare type CollectionResolveOptions = {
claim_id: string,
};
declare type CollectionListOptions = {
page: number,
page_size: number,
resolve?: boolean,
};
declare type FileListResponse = { declare type FileListResponse = {
items: Array<FileListItem>, items: Array<FileListItem>,
page: number, page: number,
@ -257,7 +209,7 @@ declare type StreamRepostOptions = {
name: string, name: string,
bid: string, bid: string,
claim_id: string, claim_id: string,
channel_id?: string, channel_id: string,
}; };
declare type StreamRepostResponse = GenericTxResponse; declare type StreamRepostResponse = GenericTxResponse;
@ -310,7 +262,6 @@ declare type LbryTypes = {
channel_update: (params: {}) => Promise<ChannelUpdateResponse>, channel_update: (params: {}) => Promise<ChannelUpdateResponse>,
channel_import: (params: {}) => Promise<string>, channel_import: (params: {}) => Promise<string>,
channel_list: (params: {}) => Promise<ChannelListResponse>, channel_list: (params: {}) => Promise<ChannelListResponse>,
channel_sign: (params: {}) => Promise<ChannelSignResponse>,
stream_abandon: (params: {}) => Promise<GenericTxResponse>, stream_abandon: (params: {}) => Promise<GenericTxResponse>,
stream_list: (params: {}) => Promise<StreamListResponse>, stream_list: (params: {}) => Promise<StreamListResponse>,
channel_abandon: (params: {}) => Promise<GenericTxResponse>, channel_abandon: (params: {}) => Promise<GenericTxResponse>,
@ -319,10 +270,6 @@ declare type LbryTypes = {
support_abandon: (params: {}) => Promise<SupportAbandonResponse>, support_abandon: (params: {}) => Promise<SupportAbandonResponse>,
stream_repost: (params: StreamRepostOptions) => Promise<StreamRepostResponse>, stream_repost: (params: StreamRepostOptions) => Promise<StreamRepostResponse>,
purchase_list: (params: PurchaseListOptions) => Promise<PurchaseListResponse>, purchase_list: (params: PurchaseListOptions) => Promise<PurchaseListResponse>,
collection_resolve: (params: CollectionResolveOptions) => Promise<CollectionResolveResponse>,
collection_list: (params: CollectionListOptions) => Promise<CollectionListResponse>,
collection_create: (params: {}) => Promise<CollectionCreateResponse>,
collection_update: (params: {}) => Promise<CollectionCreateResponse>,
// File fetching and manipulation // File fetching and manipulation
file_list: (params: {}) => Promise<FileListResponse>, file_list: (params: {}) => Promise<FileListResponse>,
@ -335,6 +282,8 @@ declare type LbryTypes = {
preference_set: (params: {}) => Promise<any>, preference_set: (params: {}) => Promise<any>,
// Commenting // Commenting
comment_list: (params: {}) => Promise<CommentListResponse>,
comment_create: (params: {}) => Promise<CommentCreateResponse>,
comment_update: (params: {}) => Promise<CommentUpdateResponse>, comment_update: (params: {}) => Promise<CommentUpdateResponse>,
comment_hide: (params: {}) => Promise<CommentHideResponse>, comment_hide: (params: {}) => Promise<CommentHideResponse>,
comment_abandon: (params: {}) => Promise<CommentAbandonResponse>, comment_abandon: (params: {}) => Promise<CommentAbandonResponse>,
@ -351,7 +300,6 @@ declare type LbryTypes = {
address_unused: (params: {}) => Promise<string>, // New address address_unused: (params: {}) => Promise<string>, // New address
address_list: (params: {}) => Promise<string>, address_list: (params: {}) => Promise<string>,
transaction_list: (params: {}) => Promise<TxListResponse>, transaction_list: (params: {}) => Promise<TxListResponse>,
txo_list: (params: {}) => Promise<any>,
// Sync // Sync
sync_hash: (params: {}) => Promise<string>, sync_hash: (params: {}) => Promise<string>,

View file

@ -10,9 +10,6 @@ declare type Txo = {
is_my_output: boolean, is_my_output: boolean,
is_my_input: boolean, is_my_input: boolean,
is_spent: boolean, is_spent: boolean,
signing_channel?: {
channel_id: string,
},
}; };
declare type TxoListParams = { declare type TxoListParams = {
@ -24,4 +21,4 @@ declare type TxoListParams = {
is_not_my_input?: boolean, is_not_my_input?: boolean,
is_not_my_output?: boolean, is_not_my_output?: boolean,
is_spent?: boolean, is_spent?: boolean,
}; }

View file

@ -1,5 +0,0 @@
// @flow
declare module '@ungap/from-entries' {
declare module.exports: any;
}

View file

@ -1,5 +0,0 @@
// @flow
declare module 'uuid' {
declare module.exports: any;
}

102
dist/flow-typed/npm/uuid_v3.x.x.js vendored Normal file
View file

@ -0,0 +1,102 @@
// flow-typed signature: 3cf668e64747095cab0bb360cf2fb34f
// flow-typed version: d659bd0cb8/uuid_v3.x.x/flow_>=v0.32.x
declare module "uuid" {
declare class uuid {
static (
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string,
static v1(
options?: {|
node?: number[],
clockseq?: number,
msecs?: number | Date,
nsecs?: number
|},
buffer?: number[] | Buffer,
offset?: number
): string,
static v4(
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<uuid>;
}
declare module "uuid/v1" {
declare class v1 {
static (
options?: {|
node?: number[],
clockseq?: number,
msecs?: number | Date,
nsecs?: number
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<v1>;
}
declare module "uuid/v3" {
declare class v3 {
static (
name?: string | number[],
namespace?: string | number[],
buffer?: number[] | Buffer,
offset?: number
): string,
static name: string,
static DNS: string,
static URL: string
}
declare module.exports: Class<v3>;
}
declare module "uuid/v4" {
declare class v4 {
static (
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<v4>;
}
declare module "uuid/v5" {
declare class v5 {
static (
name?: string | number[],
namespace?: string | number[],
buffer?: number[] | Buffer,
offset?: number
): string,
static name: string,
static DNS: string,
static URL: string
}
declare module.exports: Class<v5>;
}

83
flow-typed/Claim.js vendored
View file

@ -1,15 +1,11 @@
// @flow // @flow
declare type Claim = StreamClaim | ChannelClaim | CollectionClaim; declare type Claim = StreamClaim | ChannelClaim;
declare type ChannelClaim = GenericClaim & { declare type ChannelClaim = GenericClaim & {
value: ChannelMetadata, value: ChannelMetadata,
}; };
declare type CollectionClaim = GenericClaim & {
value: CollectionMetadata,
};
declare type StreamClaim = GenericClaim & { declare type StreamClaim = GenericClaim & {
value: StreamMetadata, value: StreamMetadata,
}; };
@ -34,12 +30,9 @@ declare type GenericClaim = {
short_url: string, // permanent_url with short id, no channel short_url: string, // permanent_url with short id, no channel
txid: string, // unique tx id txid: string, // unique tx id
type: 'claim' | 'update' | 'support', type: 'claim' | 'update' | 'support',
value_type: 'stream' | 'channel' | 'collection', value_type: 'stream' | 'channel',
signing_channel?: ChannelClaim, signing_channel?: ChannelClaim,
reposted_claim?: GenericClaim,
repost_channel_url?: string, repost_channel_url?: string,
repost_url?: string,
repost_bid_amount?: string,
purchase_receipt?: PurchaseReceipt, purchase_receipt?: PurchaseReceipt,
meta: { meta: {
activation_height: number, activation_height: number,
@ -78,10 +71,6 @@ declare type ChannelMetadata = GenericMetadata & {
featured?: Array<string>, featured?: Array<string>,
}; };
declare type CollectionMetadata = GenericMetadata & {
claims: Array<string>,
}
declare type StreamMetadata = GenericMetadata & { declare type StreamMetadata = GenericMetadata & {
license?: string, // License "title" ex: Creative Commons, Custom copyright license?: string, // License "title" ex: Creative Commons, Custom copyright
license_url?: string, // Link to full license license_url?: string, // Link to full license
@ -144,71 +133,3 @@ declare type PurchaseReceipt = {
txid: string, txid: string,
type: 'purchase', type: 'purchase',
}; };
declare type ClaimActionResolveInfo = {
[string]: {
stream: ?StreamClaim,
channel: ?ChannelClaim,
claimsInChannel: ?number,
collection: ?CollectionClaim,
},
}
declare type ChannelUpdateParams = {
claim_id: string,
bid?: string,
title?: string,
cover_url?: string,
thumbnail_url?: string,
description?: string,
website_url?: string,
email?: string,
tags?: Array<string>,
replace?: boolean,
languages?: Array<string>,
locations?: Array<string>,
blocking?: boolean,
}
declare type ChannelPublishParams = {
name: string,
bid: string,
blocking?: true,
title?: string,
cover_url?: string,
thumbnail_url?: string,
description?: string,
website_url?: string,
email?: string,
tags?: Array<string>,
languages?: Array<string>,
}
declare type CollectionUpdateParams = {
claim_id: string,
claim_ids?: Array<string>,
bid?: string,
title?: string,
cover_url?: string,
thumbnail_url?: string,
description?: string,
website_url?: string,
email?: string,
tags?: Array<string>,
replace?: boolean,
languages?: Array<string>,
locations?: Array<string>,
blocking?: boolean,
}
declare type CollectionPublishParams = {
name: string,
bid: string,
claim_ids: Array<string>,
blocking?: true,
title?: string,
thumbnail_url?: string,
description?: string,
tags?: Array<string>,
languages?: Array<string>,
}

View file

@ -1,29 +0,0 @@
declare type CoinSwapInfo = {
chargeCode: string,
coins: Array<string>,
sendAddresses: { [string]: string},
sendAmounts: { [string]: any },
lbcAmount: number,
status?: {
status: string,
receiptCurrency: string,
receiptTxid: string,
lbcTxid: string,
},
}
declare type CoinSwapState = {
coinSwaps: Array<CoinSwapInfo>,
};
declare type CoinSwapAddAction = {
type: string,
data: CoinSwapInfo,
};
declare type CoinSwapRemoveAction = {
type: string,
data: {
chargeCode: string,
},
};

View file

@ -1,34 +0,0 @@
declare type Collection = {
id: string,
items: Array<?string>,
name: string,
type: string,
updatedAt: number,
totalItems?: number,
sourceId?: string, // if copied, claimId of original collection
};
declare type CollectionState = {
unpublished: CollectionGroup,
resolved: CollectionGroup,
pending: CollectionGroup,
edited: CollectionGroup,
builtin: CollectionGroup,
saved: Array<string>,
isResolvingCollectionById: { [string]: boolean },
error?: string | null,
};
declare type CollectionGroup = {
[string]: Collection,
}
declare type CollectionEditParams = {
claims?: Array<Claim>,
remove?: boolean,
claimIds?: Array<string>,
replace?: boolean,
order?: { from: number, to: number },
type?: string,
name?: string,
}

80
flow-typed/Lbry.js vendored
View file

@ -7,6 +7,10 @@ declare type StatusResponse = {
download_progress: number, download_progress: number,
downloading_headers: boolean, downloading_headers: boolean,
}, },
connection_status: {
code: string,
message: string,
},
dht: { dht: {
node_id: string, node_id: string,
peers_in_routing_table: number, peers_in_routing_table: number,
@ -41,7 +45,6 @@ declare type StatusResponse = {
redirects: {}, redirects: {},
}, },
wallet: ?{ wallet: ?{
connected: string,
best_blockhash: string, best_blockhash: string,
blocks: number, blocks: number,
blocks_behind: number, blocks_behind: number,
@ -75,7 +78,7 @@ declare type BalanceResponse = {
declare type ResolveResponse = { declare type ResolveResponse = {
// Keys are the url(s) passed to resolve // Keys are the url(s) passed to resolve
[string]: { error?: {}, stream?: StreamClaim, channel?: ChannelClaim, collection?: CollectionClaim, claimsInChannel?: number }, [string]: { error?: {}, stream?: StreamClaim, channel?: ChannelClaim, claimsInChannel?: number },
}; };
declare type GetResponse = FileListItem & { error?: string }; declare type GetResponse = FileListItem & { error?: string };
@ -124,22 +127,12 @@ declare type ChannelUpdateResponse = GenericTxResponse & {
declare type CommentCreateResponse = Comment; declare type CommentCreateResponse = Comment;
declare type CommentUpdateResponse = Comment; declare type CommentUpdateResponse = Comment;
declare type MyReactions = { declare type CommentListResponse = {
// Keys are the commentId items: Array<Comment>,
[string]: Array<string>, page: number,
}; page_size: number,
total_items: number,
declare type OthersReactions = { total_pages: number,
// Keys are the commentId
[string]: {
// Keys are the reaction_type, e.g. 'like'
[string]: number,
},
};
declare type CommentReactListResponse = {
my_reactions: Array<MyReactions>,
others_reactions: Array<OthersReactions>,
}; };
declare type CommentHideResponse = { declare type CommentHideResponse = {
@ -147,11 +140,6 @@ declare type CommentHideResponse = {
[string]: { hidden: boolean }, [string]: { hidden: boolean },
}; };
declare type CommentPinResponse = {
// keyed by the CommentIds entered
items: Comment,
};
declare type CommentAbandonResponse = { declare type CommentAbandonResponse = {
// keyed by the CommentId given // keyed by the CommentId given
abandoned: boolean, abandoned: boolean,
@ -165,42 +153,6 @@ declare type ChannelListResponse = {
total_pages: number, total_pages: number,
}; };
declare type ChannelSignResponse = {
signature: string,
signing_ts: string,
};
declare type CollectionCreateResponse = {
outputs: Array<Claim>,
page: number,
page_size: number,
total_items: number,
total_pages: number,
}
declare type CollectionListResponse = {
items: Array<Claim>,
page: number,
page_size: number,
total_items: number,
total_pages: number,
};
declare type CollectionResolveResponse = {
items: Array<Claim>,
total_items: number,
};
declare type CollectionResolveOptions = {
claim_id: string,
};
declare type CollectionListOptions = {
page: number,
page_size: number,
resolve?: boolean,
};
declare type FileListResponse = { declare type FileListResponse = {
items: Array<FileListItem>, items: Array<FileListItem>,
page: number, page: number,
@ -257,7 +209,7 @@ declare type StreamRepostOptions = {
name: string, name: string,
bid: string, bid: string,
claim_id: string, claim_id: string,
channel_id?: string, channel_id: string,
}; };
declare type StreamRepostResponse = GenericTxResponse; declare type StreamRepostResponse = GenericTxResponse;
@ -310,7 +262,6 @@ declare type LbryTypes = {
channel_update: (params: {}) => Promise<ChannelUpdateResponse>, channel_update: (params: {}) => Promise<ChannelUpdateResponse>,
channel_import: (params: {}) => Promise<string>, channel_import: (params: {}) => Promise<string>,
channel_list: (params: {}) => Promise<ChannelListResponse>, channel_list: (params: {}) => Promise<ChannelListResponse>,
channel_sign: (params: {}) => Promise<ChannelSignResponse>,
stream_abandon: (params: {}) => Promise<GenericTxResponse>, stream_abandon: (params: {}) => Promise<GenericTxResponse>,
stream_list: (params: {}) => Promise<StreamListResponse>, stream_list: (params: {}) => Promise<StreamListResponse>,
channel_abandon: (params: {}) => Promise<GenericTxResponse>, channel_abandon: (params: {}) => Promise<GenericTxResponse>,
@ -319,10 +270,6 @@ declare type LbryTypes = {
support_abandon: (params: {}) => Promise<SupportAbandonResponse>, support_abandon: (params: {}) => Promise<SupportAbandonResponse>,
stream_repost: (params: StreamRepostOptions) => Promise<StreamRepostResponse>, stream_repost: (params: StreamRepostOptions) => Promise<StreamRepostResponse>,
purchase_list: (params: PurchaseListOptions) => Promise<PurchaseListResponse>, purchase_list: (params: PurchaseListOptions) => Promise<PurchaseListResponse>,
collection_resolve: (params: CollectionResolveOptions) => Promise<CollectionResolveResponse>,
collection_list: (params: CollectionListOptions) => Promise<CollectionListResponse>,
collection_create: (params: {}) => Promise<CollectionCreateResponse>,
collection_update: (params: {}) => Promise<CollectionCreateResponse>,
// File fetching and manipulation // File fetching and manipulation
file_list: (params: {}) => Promise<FileListResponse>, file_list: (params: {}) => Promise<FileListResponse>,
@ -335,6 +282,8 @@ declare type LbryTypes = {
preference_set: (params: {}) => Promise<any>, preference_set: (params: {}) => Promise<any>,
// Commenting // Commenting
comment_list: (params: {}) => Promise<CommentListResponse>,
comment_create: (params: {}) => Promise<CommentCreateResponse>,
comment_update: (params: {}) => Promise<CommentUpdateResponse>, comment_update: (params: {}) => Promise<CommentUpdateResponse>,
comment_hide: (params: {}) => Promise<CommentHideResponse>, comment_hide: (params: {}) => Promise<CommentHideResponse>,
comment_abandon: (params: {}) => Promise<CommentAbandonResponse>, comment_abandon: (params: {}) => Promise<CommentAbandonResponse>,
@ -351,7 +300,6 @@ declare type LbryTypes = {
address_unused: (params: {}) => Promise<string>, // New address address_unused: (params: {}) => Promise<string>, // New address
address_list: (params: {}) => Promise<string>, address_list: (params: {}) => Promise<string>,
transaction_list: (params: {}) => Promise<TxListResponse>, transaction_list: (params: {}) => Promise<TxListResponse>,
txo_list: (params: {}) => Promise<any>,
// Sync // Sync
sync_hash: (params: {}) => Promise<string>, sync_hash: (params: {}) => Promise<string>,

5
flow-typed/Txo.js vendored
View file

@ -10,9 +10,6 @@ declare type Txo = {
is_my_output: boolean, is_my_output: boolean,
is_my_input: boolean, is_my_input: boolean,
is_spent: boolean, is_spent: boolean,
signing_channel?: {
channel_id: string,
},
}; };
declare type TxoListParams = { declare type TxoListParams = {
@ -24,4 +21,4 @@ declare type TxoListParams = {
is_not_my_input?: boolean, is_not_my_input?: boolean,
is_not_my_output?: boolean, is_not_my_output?: boolean,
is_spent?: boolean, is_spent?: boolean,
}; }

View file

@ -1,5 +0,0 @@
// @flow
declare module '@ungap/from-entries' {
declare module.exports: any;
}

View file

@ -1,5 +0,0 @@
// @flow
declare module 'uuid' {
declare module.exports: any;
}

102
flow-typed/npm/uuid_v3.x.x.js vendored Normal file
View file

@ -0,0 +1,102 @@
// flow-typed signature: 3cf668e64747095cab0bb360cf2fb34f
// flow-typed version: d659bd0cb8/uuid_v3.x.x/flow_>=v0.32.x
declare module "uuid" {
declare class uuid {
static (
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string,
static v1(
options?: {|
node?: number[],
clockseq?: number,
msecs?: number | Date,
nsecs?: number
|},
buffer?: number[] | Buffer,
offset?: number
): string,
static v4(
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<uuid>;
}
declare module "uuid/v1" {
declare class v1 {
static (
options?: {|
node?: number[],
clockseq?: number,
msecs?: number | Date,
nsecs?: number
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<v1>;
}
declare module "uuid/v3" {
declare class v3 {
static (
name?: string | number[],
namespace?: string | number[],
buffer?: number[] | Buffer,
offset?: number
): string,
static name: string,
static DNS: string,
static URL: string
}
declare module.exports: Class<v3>;
}
declare module "uuid/v4" {
declare class v4 {
static (
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<v4>;
}
declare module "uuid/v5" {
declare class v5 {
static (
name?: string | number[],
namespace?: string | number[],
buffer?: number[] | Buffer,
offset?: number
): string,
static name: string,
static DNS: string,
static URL: string
}
declare module.exports: Class<v5>;
}

View file

@ -29,10 +29,9 @@
"test": "jest" "test": "jest"
}, },
"dependencies": { "dependencies": {
"@ungap/from-entries": "^0.2.1",
"proxy-polyfill": "0.1.6", "proxy-polyfill": "0.1.6",
"reselect": "^3.0.0", "reselect": "^3.0.0",
"uuid": "^8.3.1" "uuid": "^3.3.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.10.4", "@babel/plugin-proposal-class-properties": "^7.10.4",

View file

@ -79,16 +79,6 @@ export const SET_TRANSACTION_LIST_FILTER = 'SET_TRANSACTION_LIST_FILTER';
export const UPDATE_CURRENT_HEIGHT = 'UPDATE_CURRENT_HEIGHT'; export const UPDATE_CURRENT_HEIGHT = 'UPDATE_CURRENT_HEIGHT';
export const SET_DRAFT_TRANSACTION_AMOUNT = 'SET_DRAFT_TRANSACTION_AMOUNT'; export const SET_DRAFT_TRANSACTION_AMOUNT = 'SET_DRAFT_TRANSACTION_AMOUNT';
export const SET_DRAFT_TRANSACTION_ADDRESS = 'SET_DRAFT_TRANSACTION_ADDRESS'; export const SET_DRAFT_TRANSACTION_ADDRESS = 'SET_DRAFT_TRANSACTION_ADDRESS';
export const FETCH_UTXO_COUNT_STARTED = 'FETCH_UTXO_COUNT_STARTED';
export const FETCH_UTXO_COUNT_COMPLETED = 'FETCH_UTXO_COUNT_COMPLETED';
export const FETCH_UTXO_COUNT_FAILED = 'FETCH_UTXO_COUNT_FAILED';
export const TIP_CLAIM_MASS_STARTED = 'TIP_CLAIM_MASS_STARTED';
export const TIP_CLAIM_MASS_COMPLETED = 'TIP_CLAIM_MASS_COMPLETED';
export const TIP_CLAIM_MASS_FAILED = 'TIP_CLAIM_MASS_FAILED';
export const DO_UTXO_CONSOLIDATE_STARTED = 'DO_UTXO_CONSOLIDATE_STARTED';
export const DO_UTXO_CONSOLIDATE_COMPLETED = 'DO_UTXO_CONSOLIDATE_COMPLETED';
export const DO_UTXO_CONSOLIDATE_FAILED = 'DO_UTXO_CONSOLIDATE_FAILED';
export const PENDING_CONSOLIDATED_TXOS_UPDATED = 'PENDING_CONSOLIDATED_TXOS_UPDATED';
// Claims // Claims
export const RESOLVE_URIS_STARTED = 'RESOLVE_URIS_STARTED'; export const RESOLVE_URIS_STARTED = 'RESOLVE_URIS_STARTED';
@ -102,9 +92,6 @@ export const ABANDON_CLAIM_SUCCEEDED = 'ABANDON_CLAIM_SUCCEEDED';
export const FETCH_CHANNEL_LIST_STARTED = 'FETCH_CHANNEL_LIST_STARTED'; export const FETCH_CHANNEL_LIST_STARTED = 'FETCH_CHANNEL_LIST_STARTED';
export const FETCH_CHANNEL_LIST_COMPLETED = 'FETCH_CHANNEL_LIST_COMPLETED'; export const FETCH_CHANNEL_LIST_COMPLETED = 'FETCH_CHANNEL_LIST_COMPLETED';
export const FETCH_CHANNEL_LIST_FAILED = 'FETCH_CHANNEL_LIST_FAILED'; export const FETCH_CHANNEL_LIST_FAILED = 'FETCH_CHANNEL_LIST_FAILED';
export const FETCH_COLLECTION_LIST_STARTED = 'FETCH_COLLECTION_LIST_STARTED';
export const FETCH_COLLECTION_LIST_COMPLETED = 'FETCH_COLLECTION_LIST_COMPLETED';
export const FETCH_COLLECTION_LIST_FAILED = 'FETCH_COLLECTION_LIST_FAILED';
export const CREATE_CHANNEL_STARTED = 'CREATE_CHANNEL_STARTED'; export const CREATE_CHANNEL_STARTED = 'CREATE_CHANNEL_STARTED';
export const CREATE_CHANNEL_COMPLETED = 'CREATE_CHANNEL_COMPLETED'; export const CREATE_CHANNEL_COMPLETED = 'CREATE_CHANNEL_COMPLETED';
export const CREATE_CHANNEL_FAILED = 'CREATE_CHANNEL_FAILED'; export const CREATE_CHANNEL_FAILED = 'CREATE_CHANNEL_FAILED';
@ -114,7 +101,6 @@ export const UPDATE_CHANNEL_FAILED = 'UPDATE_CHANNEL_FAILED';
export const IMPORT_CHANNEL_STARTED = 'IMPORT_CHANNEL_STARTED'; export const IMPORT_CHANNEL_STARTED = 'IMPORT_CHANNEL_STARTED';
export const IMPORT_CHANNEL_COMPLETED = 'IMPORT_CHANNEL_COMPLETED'; export const IMPORT_CHANNEL_COMPLETED = 'IMPORT_CHANNEL_COMPLETED';
export const IMPORT_CHANNEL_FAILED = 'IMPORT_CHANNEL_FAILED'; export const IMPORT_CHANNEL_FAILED = 'IMPORT_CHANNEL_FAILED';
export const CLEAR_CHANNEL_ERRORS = 'CLEAR_CHANNEL_ERRORS';
export const PUBLISH_STARTED = 'PUBLISH_STARTED'; export const PUBLISH_STARTED = 'PUBLISH_STARTED';
export const PUBLISH_COMPLETED = 'PUBLISH_COMPLETED'; export const PUBLISH_COMPLETED = 'PUBLISH_COMPLETED';
export const PUBLISH_FAILED = 'PUBLISH_FAILED'; export const PUBLISH_FAILED = 'PUBLISH_FAILED';
@ -133,6 +119,7 @@ export const CLAIM_REPOST_STARTED = 'CLAIM_REPOST_STARTED';
export const CLAIM_REPOST_COMPLETED = 'CLAIM_REPOST_COMPLETED'; export const CLAIM_REPOST_COMPLETED = 'CLAIM_REPOST_COMPLETED';
export const CLAIM_REPOST_FAILED = 'CLAIM_REPOST_FAILED'; export const CLAIM_REPOST_FAILED = 'CLAIM_REPOST_FAILED';
export const CLEAR_REPOST_ERROR = 'CLEAR_REPOST_ERROR'; export const CLEAR_REPOST_ERROR = 'CLEAR_REPOST_ERROR';
export const CLEAR_CHANNEL_ERRORS = 'CLEAR_CHANNEL_ERRORS';
export const CHECK_PUBLISH_NAME_STARTED = 'CHECK_PUBLISH_NAME_STARTED'; export const CHECK_PUBLISH_NAME_STARTED = 'CHECK_PUBLISH_NAME_STARTED';
export const CHECK_PUBLISH_NAME_COMPLETED = 'CHECK_PUBLISH_NAME_COMPLETED'; export const CHECK_PUBLISH_NAME_COMPLETED = 'CHECK_PUBLISH_NAME_COMPLETED';
export const UPDATE_PENDING_CLAIMS = 'UPDATE_PENDING_CLAIMS'; export const UPDATE_PENDING_CLAIMS = 'UPDATE_PENDING_CLAIMS';
@ -145,27 +132,6 @@ export const PURCHASE_LIST_STARTED = 'PURCHASE_LIST_STARTED';
export const PURCHASE_LIST_COMPLETED = 'PURCHASE_LIST_COMPLETED'; export const PURCHASE_LIST_COMPLETED = 'PURCHASE_LIST_COMPLETED';
export const PURCHASE_LIST_FAILED = 'PURCHASE_LIST_FAILED'; export const PURCHASE_LIST_FAILED = 'PURCHASE_LIST_FAILED';
export const COLLECTION_PUBLISH_STARTED = 'COLLECTION_PUBLISH_STARTED';
export const COLLECTION_PUBLISH_COMPLETED = 'COLLECTION_PUBLISH_COMPLETED';
export const COLLECTION_PUBLISH_FAILED = 'COLLECTION_PUBLISH_FAILED';
export const COLLECTION_PUBLISH_UPDATE_STARTED = 'COLLECTION_PUBLISH_UPDATE_STARTED';
export const COLLECTION_PUBLISH_UPDATE_COMPLETED = 'COLLECTION_PUBLISH_UPDATE_COMPLETED';
export const COLLECTION_PUBLISH_UPDATE_FAILED = 'COLLECTION_PUBLISH_UPDATE_FAILED';
export const COLLECTION_PUBLISH_ABANDON_STARTED = 'COLLECTION_PUBLISH_ABANDON_STARTED';
export const COLLECTION_PUBLISH_ABANDON_COMPLETED = 'COLLECTION_PUBLISH_ABANDON_COMPLETED';
export const COLLECTION_PUBLISH_ABANDON_FAILED = 'COLLECTION_PUBLISH_ABANDON_FAILED';
export const CLEAR_COLLECTION_ERRORS = 'CLEAR_COLLECTION_ERRORS';
export const COLLECTION_ITEMS_RESOLVE_STARTED = 'COLLECTION_ITEMS_RESOLVE_STARTED';
export const COLLECTION_ITEMS_RESOLVE_COMPLETED = 'COLLECTION_ITEMS_RESOLVE_COMPLETED';
export const COLLECTION_ITEMS_RESOLVE_FAILED = 'COLLECTION_ITEMS_RESOLVE_FAILED';
export const COLLECTION_NEW = 'COLLECTION_NEW';
export const COLLECTION_DELETE = 'COLLECTION_DELETE';
export const COLLECTION_PENDING = 'COLLECTION_PENDING';
export const COLLECTION_EDIT = 'COLLECTION_EDIT';
export const COLLECTION_COPY = 'COLLECTION_COPY';
export const COLLECTION_SAVE = 'COLLECTION_SAVE';
export const COLLECTION_ERROR = 'COLLECTION_ERROR';
// Comments // Comments
export const COMMENT_LIST_STARTED = 'COMMENT_LIST_STARTED'; export const COMMENT_LIST_STARTED = 'COMMENT_LIST_STARTED';
export const COMMENT_LIST_COMPLETED = 'COMMENT_LIST_COMPLETED'; export const COMMENT_LIST_COMPLETED = 'COMMENT_LIST_COMPLETED';
@ -300,6 +266,10 @@ export const FETCH_COST_INFO_STARTED = 'FETCH_COST_INFO_STARTED';
export const FETCH_COST_INFO_COMPLETED = 'FETCH_COST_INFO_COMPLETED'; export const FETCH_COST_INFO_COMPLETED = 'FETCH_COST_INFO_COMPLETED';
export const FETCH_COST_INFO_FAILED = 'FETCH_COST_INFO_FAILED'; export const FETCH_COST_INFO_FAILED = 'FETCH_COST_INFO_FAILED';
// Tags
export const TOGGLE_TAG_FOLLOW = 'TOGGLE_TAG_FOLLOW';
export const TAG_ADD = 'TAG_ADD';
export const TAG_DELETE = 'TAG_DELETE';
// Sync // Sync
export const USER_STATE_POPULATE = 'USER_STATE_POPULATE'; export const USER_STATE_POPULATE = 'USER_STATE_POPULATE';
export const SYNC_FATAL_ERROR = 'SYNC_FATAL_ERROR';

View file

@ -3,9 +3,3 @@ export const MINIMUM_PUBLISH_BID = 0.00000001;
export const CHANNEL_ANONYMOUS = 'anonymous'; export const CHANNEL_ANONYMOUS = 'anonymous';
export const CHANNEL_NEW = 'new'; export const CHANNEL_NEW = 'new';
export const PAGE_SIZE = 20; export const PAGE_SIZE = 20;
export const LEVEL_1_STAKED_AMOUNT = 0;
export const LEVEL_2_STAKED_AMOUNT = 1;
export const LEVEL_3_STAKED_AMOUNT = 50;
export const LEVEL_4_STAKED_AMOUNT = 250;
export const LEVEL_5_STAKED_AMOUNT = 1000;

View file

@ -1,15 +0,0 @@
export const COLLECTION_ID = 'lid';
export const COLLECTION_INDEX = 'linx';
export const COL_TYPE_PLAYLIST = 'playlist';
export const COL_TYPE_CHANNELS = 'channelList';
export const WATCH_LATER_ID = 'watchlater';
export const FAVORITES_ID = 'favorites';
export const FAVORITE_CHANNELS_ID = 'favoriteChannels';
export const BUILTIN_LISTS = [WATCH_LATER_ID, FAVORITES_ID, FAVORITE_CHANNELS_ID];
export const COL_KEY_EDITED = 'edited';
export const COL_KEY_UNPUBLISHED = 'unpublished';
export const COL_KEY_PENDING = 'pending';
export const COL_KEY_SAVED = 'saved';

View file

@ -12,9 +12,7 @@ export const FOLLOWING_ACKNOWLEDGED = 'following_acknowledged';
export const TAGS_ACKNOWLEDGED = 'tags_acknowledged'; export const TAGS_ACKNOWLEDGED = 'tags_acknowledged';
export const REWARDS_ACKNOWLEDGED = 'rewards_acknowledged'; export const REWARDS_ACKNOWLEDGED = 'rewards_acknowledged';
export const LANGUAGE = 'language'; export const LANGUAGE = 'language';
export const SEARCH_IN_LANGUAGE = 'search_in_language';
export const SHOW_MATURE = 'show_mature'; export const SHOW_MATURE = 'show_mature';
export const HOMEPAGE = 'homepage';
export const HIDE_REPOSTS = 'hide_reposts'; export const HIDE_REPOSTS = 'hide_reposts';
export const SHOW_ANONYMOUS = 'show_anonymous'; export const SHOW_ANONYMOUS = 'show_anonymous';
export const SHOW_UNAVAILABLE = 'show_unavailable'; export const SHOW_UNAVAILABLE = 'show_unavailable';
@ -23,7 +21,7 @@ export const INSTANT_PURCHASE_MAX = 'instant_purchase_max';
export const THEME = 'theme'; export const THEME = 'theme';
export const THEMES = 'themes'; export const THEMES = 'themes';
export const AUTOMATIC_DARK_MODE_ENABLED = 'automatic_dark_mode_enabled'; export const AUTOMATIC_DARK_MODE_ENABLED = 'automatic_dark_mode_enabled';
export const AUTOPLAY_MEDIA = 'autoplay'; export const AUTOPLAY = 'autoplay';
export const AUTOPLAY_NEXT = 'autoplay_next'; export const AUTOPLAY_NEXT = 'autoplay_next';
export const OS_NOTIFICATIONS_ENABLED = 'os_notifications_enabled'; export const OS_NOTIFICATIONS_ENABLED = 'os_notifications_enabled';
export const AUTO_DOWNLOAD = 'auto_download'; export const AUTO_DOWNLOAD = 'auto_download';
@ -38,9 +36,6 @@ export const ENABLE_SYNC = 'enable_sync';
export const ENABLE_PUBLISH_PREVIEW = 'enable-publish-preview'; export const ENABLE_PUBLISH_PREVIEW = 'enable-publish-preview';
export const TILE_LAYOUT = 'tile_layout'; export const TILE_LAYOUT = 'tile_layout';
export const VIDEO_THEATER_MODE = 'video_theater_mode'; export const VIDEO_THEATER_MODE = 'video_theater_mode';
export const VIDEO_PLAYBACK_RATE = 'video_playback_rate';
export const CUSTOM_COMMENTS_SERVER_ENABLED = 'custom_comments_server_enabled';
export const CUSTOM_COMMENTS_SERVER_URL = 'custom_comments_server_url';
// mobile settings // mobile settings
export const BACKGROUND_PLAY_ENABLED = 'backgroundPlayEnabled'; export const BACKGROUND_PLAY_ENABLED = 'backgroundPlayEnabled';

View file

@ -21,12 +21,10 @@ export const CLIENT_SYNC_KEYS = [
SETTINGS.INSTANT_PURCHASE_ENABLED, SETTINGS.INSTANT_PURCHASE_ENABLED,
SETTINGS.INSTANT_PURCHASE_MAX, SETTINGS.INSTANT_PURCHASE_MAX,
SETTINGS.THEME, SETTINGS.THEME,
SETTINGS.AUTOPLAY_MEDIA, SETTINGS.AUTOPLAY,
SETTINGS.AUTOPLAY_NEXT,
SETTINGS.HIDE_BALANCE, SETTINGS.HIDE_BALANCE,
SETTINGS.HIDE_SPLASH_ANIMATION, SETTINGS.HIDE_SPLASH_ANIMATION,
SETTINGS.FLOATING_PLAYER, SETTINGS.FLOATING_PLAYER,
SETTINGS.DARK_MODE_TIMES, SETTINGS.DARK_MODE_TIMES,
SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, SETTINGS.AUTOMATIC_DARK_MODE_ENABLED,
SETTINGS.LANGUAGE,
]; ];

View file

@ -520,8 +520,6 @@ const DEFAULT_ENGLISH_KNOWN_TAGS = [
'2020protests', '2020protests',
'covidcuts', 'covidcuts',
'covid-19', 'covid-19',
'LBRYFoundationBoardCandidacy',
'helplbrysavecrypto'
]; ];
const DEFAULT_SPANISH_KNOWN_TAGS = [ const DEFAULT_SPANISH_KNOWN_TAGS = [

View file

@ -12,7 +12,6 @@ import * as TXO_LIST from 'constants/txo_list';
import * as SPEECH_URLS from 'constants/speech_urls'; import * as SPEECH_URLS from 'constants/speech_urls';
import * as DAEMON_SETTINGS from 'constants/daemon_settings'; import * as DAEMON_SETTINGS from 'constants/daemon_settings';
import * as SHARED_PREFERENCES from 'constants/shared_preferences'; import * as SHARED_PREFERENCES from 'constants/shared_preferences';
import * as COLLECTIONS_CONSTS from 'constants/collections';
import { DEFAULT_KNOWN_TAGS, DEFAULT_FOLLOWED_TAGS, MATURE_TAGS } from 'constants/tags'; import { DEFAULT_KNOWN_TAGS, DEFAULT_FOLLOWED_TAGS, MATURE_TAGS } from 'constants/tags';
import Lbry, { apiCall } from 'lbry'; import Lbry, { apiCall } from 'lbry';
import LbryFirst from 'lbry-first'; import LbryFirst from 'lbry-first';
@ -36,7 +35,6 @@ export {
MATURE_TAGS, MATURE_TAGS,
SPEECH_URLS, SPEECH_URLS,
SHARED_PREFERENCES, SHARED_PREFERENCES,
COLLECTIONS_CONSTS,
}; };
// common // common
@ -52,8 +50,6 @@ export {
isURIClaimable, isURIClaimable,
isNameValid, isNameValid,
convertToShareLink, convertToShareLink,
splitBySeparator,
isURIEqual,
} from 'lbryURI'; } from 'lbryURI';
// middlware // middlware
@ -61,13 +57,6 @@ export { buildSharedStateMiddleware } from 'redux/middleware/shared-state';
// actions // actions
export { doToast, doDismissToast, doError, doDismissError } from 'redux/actions/notifications'; export { doToast, doDismissToast, doError, doDismissError } from 'redux/actions/notifications';
export {
doLocalCollectionCreate,
doFetchItemsInCollection,
doFetchItemsInCollections,
doCollectionEdit,
doCollectionDelete,
} from 'redux/actions/collections';
export { export {
doFetchClaimsByChannel, doFetchClaimsByChannel,
@ -77,7 +66,6 @@ export {
doResolveUris, doResolveUris,
doResolveUri, doResolveUri,
doFetchChannelListMine, doFetchChannelListMine,
doFetchCollectionListMine,
doCreateChannel, doCreateChannel,
doUpdateChannel, doUpdateChannel,
doClaimSearch, doClaimSearch,
@ -88,8 +76,6 @@ export {
doCheckPublishNameAvailability, doCheckPublishNameAvailability,
doPurchaseList, doPurchaseList,
doCheckPendingClaims, doCheckPendingClaims,
doCollectionPublish,
doCollectionPublishUpdate,
} from 'redux/actions/claims'; } from 'redux/actions/claims';
export { doClearPurchasedUriSuccess, doPurchaseUri, doFileGet } from 'redux/actions/file'; export { doClearPurchasedUriSuccess, doPurchaseUri, doFileGet } from 'redux/actions/file';
@ -134,11 +120,10 @@ export {
doUpdateBlockHeight, doUpdateBlockHeight,
doClearSupport, doClearSupport,
doSupportAbandonForClaim, doSupportAbandonForClaim,
doFetchUtxoCounts,
doUtxoConsolidate,
doTipClaimMass,
} from 'redux/actions/wallet'; } from 'redux/actions/wallet';
export { doToggleTagFollow, doAddTag, doDeleteTag } from 'redux/actions/tags';
export { doPopulateSharedUserState, doPreferenceGet, doPreferenceSet } from 'redux/actions/sync'; export { doPopulateSharedUserState, doPreferenceGet, doPreferenceSet } from 'redux/actions/sync';
// utils // utils
@ -153,40 +138,13 @@ export { contentReducer } from 'redux/reducers/content';
export { fileInfoReducer } from 'redux/reducers/file_info'; export { fileInfoReducer } from 'redux/reducers/file_info';
export { notificationsReducer } from 'redux/reducers/notifications'; export { notificationsReducer } from 'redux/reducers/notifications';
export { publishReducer } from 'redux/reducers/publish'; export { publishReducer } from 'redux/reducers/publish';
export { tagsReducer } from 'redux/reducers/tags';
export { walletReducer } from 'redux/reducers/wallet'; export { walletReducer } from 'redux/reducers/wallet';
export { collectionsReducer } from 'redux/reducers/collections';
// selectors // selectors
export { makeSelectContentPositionForUri } from 'redux/selectors/content'; export { makeSelectContentPositionForUri } from 'redux/selectors/content';
export { selectToast, selectError } from 'redux/selectors/notifications'; export { selectToast, selectError } from 'redux/selectors/notifications';
export {
selectSavedCollectionIds,
selectBuiltinCollections,
selectResolvedCollections,
selectMyUnpublishedCollections,
selectMyEditedCollections,
selectMyPublishedCollections,
selectMyPublishedMixedCollections,
selectMyPublishedPlaylistCollections,
makeSelectEditedCollectionForId,
makeSelectPendingCollectionForId,
makeSelectPublishedCollectionForId,
makeSelectCollectionIsMine,
makeSelectMyPublishedCollectionForId,
makeSelectUnpublishedCollectionForId,
makeSelectCollectionForId,
makeSelectClaimUrlInCollection,
makeSelectUrlsForCollectionId,
makeSelectClaimIdsForCollectionId,
makeSelectNameForCollectionId,
makeSelectCountForCollectionId,
makeSelectIsResolvingCollectionForId,
makeSelectIndexForUrlInCollection,
makeSelectPreviousUrlForCollectionAndUrl,
makeSelectNextUrlForCollectionAndUrl,
makeSelectCollectionForIdHasClaimUrl,
} from 'redux/selectors/collections';
export { export {
makeSelectClaimForUri, makeSelectClaimForUri,
@ -202,24 +160,19 @@ export {
makeSelectTitleForUri, makeSelectTitleForUri,
makeSelectDateForUri, makeSelectDateForUri,
makeSelectAmountForUri, makeSelectAmountForUri,
makeSelectEffectiveAmountForUri,
makeSelectTagsForUri, makeSelectTagsForUri,
makeSelectTagInClaimOrChannelForUri,
makeSelectTotalStakedAmountForChannelUri,
makeSelectStakedLevelForChannelUri,
makeSelectContentTypeForUri, makeSelectContentTypeForUri,
makeSelectIsUriResolving, makeSelectIsUriResolving,
makeSelectPendingClaimForUri,
makeSelectTotalItemsForChannel, makeSelectTotalItemsForChannel,
makeSelectTotalPagesForChannel, makeSelectTotalPagesForChannel,
makeSelectNsfwCountFromUris, makeSelectNsfwCountFromUris,
makeSelectNsfwCountForChannel,
makeSelectOmittedCountForChannel, makeSelectOmittedCountForChannel,
makeSelectClaimIsNsfw, makeSelectClaimIsNsfw,
makeSelectChannelForClaimUri, makeSelectChannelForClaimUri,
makeSelectChannelPermUrlForClaimUri,
makeSelectMyChannelPermUrlForName,
makeSelectClaimIsPending, makeSelectClaimIsPending,
makeSelectReflectingClaimForUri, makeSelectReflectingClaimForUri,
makeSelectClaimsInChannelForCurrentPageState,
makeSelectShortUrlForUri, makeSelectShortUrlForUri,
makeSelectCanonicalUrlForUri, makeSelectCanonicalUrlForUri,
makeSelectPermanentUrlForUri, makeSelectPermanentUrlForUri,
@ -228,11 +181,7 @@ export {
makeSelectClaimWasPurchased, makeSelectClaimWasPurchased,
makeSelectAbandoningClaimById, makeSelectAbandoningClaimById,
makeSelectIsAbandoningClaimForUri, makeSelectIsAbandoningClaimForUri,
makeSelectClaimHasSource,
makeSelectClaimIsStreamPlaceholder,
selectPendingIds,
selectReflectingById, selectReflectingById,
makeSelectClaimForClaimId,
selectClaimsById, selectClaimsById,
selectClaimsByUri, selectClaimsByUri,
selectAllClaimsByChannel, selectAllClaimsByChannel,
@ -242,15 +191,12 @@ export {
selectAllFetchingChannelClaims, selectAllFetchingChannelClaims,
selectIsFetchingClaimListMine, selectIsFetchingClaimListMine,
selectMyClaims, selectMyClaims,
selectPendingClaims,
selectMyClaimsWithoutChannels, selectMyClaimsWithoutChannels,
selectMyChannelUrls, selectMyChannelUrls,
selectMyClaimUrisWithoutChannels, selectMyClaimUrisWithoutChannels,
selectAllMyClaimsByOutpoint, selectAllMyClaimsByOutpoint,
selectMyClaimsOutpoints, selectMyClaimsOutpoints,
selectFetchingMyChannels, selectFetchingMyChannels,
selectFetchingMyCollections,
selectMyCollectionIds,
selectMyChannelClaims, selectMyChannelClaims,
selectResolvingUris, selectResolvingUris,
selectPlayingUri, selectPlayingUri,
@ -279,12 +225,6 @@ export {
selectFetchingMyPurchasesError, selectFetchingMyPurchasesError,
selectMyPurchasesCount, selectMyPurchasesCount,
selectPurchaseUriSuccess, selectPurchaseUriSuccess,
makeSelectClaimIdForUri,
selectUpdatingCollection,
selectUpdateCollectionError,
selectCreatingCollection,
selectCreateCollectionError,
makeSelectClaimIdIsPending,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
export { export {
@ -333,7 +273,6 @@ export {
selectSupportsByOutpoint, selectSupportsByOutpoint,
selectTotalSupports, selectTotalSupports,
selectTransactionItems, selectTransactionItems,
selectTransactionsFile,
selectRecentTransactions, selectRecentTransactions,
selectHasTransactions, selectHasTransactions,
selectIsFetchingTransactions, selectIsFetchingTransactions,
@ -371,11 +310,11 @@ export {
selectPendingSupportTransactions, selectPendingSupportTransactions,
selectAbandonClaimSupportError, selectAbandonClaimSupportError,
makeSelectPendingAmountByUri, makeSelectPendingAmountByUri,
selectIsFetchingUtxoCounts,
selectIsConsolidatingUtxos,
selectIsMassClaimingTips,
selectUtxoCounts,
selectPendingOtherTransactions,
selectPendingConsolidateTxid,
selectPendingMassClaimTxid,
} from 'redux/selectors/wallet'; } from 'redux/selectors/wallet';
export {
selectFollowedTags,
selectFollowedTagsList,
selectUnfollowedTags,
makeSelectIsFollowingTag,
} from 'redux/selectors/tags';

View file

@ -86,14 +86,9 @@ const Lbry: LbryTypes = {
stream_abandon: params => daemonCallWithResult('stream_abandon', params), stream_abandon: params => daemonCallWithResult('stream_abandon', params),
stream_list: params => daemonCallWithResult('stream_list', params), stream_list: params => daemonCallWithResult('stream_list', params),
channel_abandon: params => daemonCallWithResult('channel_abandon', params), channel_abandon: params => daemonCallWithResult('channel_abandon', params),
channel_sign: params => daemonCallWithResult('channel_sign', params),
support_create: params => daemonCallWithResult('support_create', params), support_create: params => daemonCallWithResult('support_create', params),
support_list: params => daemonCallWithResult('support_list', params), support_list: params => daemonCallWithResult('support_list', params),
stream_repost: params => daemonCallWithResult('stream_repost', params), stream_repost: params => daemonCallWithResult('stream_repost', params),
collection_resolve: params => daemonCallWithResult('collection_resolve', params),
collection_list: params => daemonCallWithResult('collection_list', params),
collection_create: params => daemonCallWithResult('collection_create', params),
collection_update: params => daemonCallWithResult('collection_update', params),
// File fetching and manipulation // File fetching and manipulation
file_list: (params = {}) => daemonCallWithResult('file_list', params), file_list: (params = {}) => daemonCallWithResult('file_list', params),
@ -117,7 +112,6 @@ const Lbry: LbryTypes = {
utxo_release: (params = {}) => daemonCallWithResult('utxo_release', params), utxo_release: (params = {}) => daemonCallWithResult('utxo_release', params),
support_abandon: (params = {}) => daemonCallWithResult('support_abandon', params), support_abandon: (params = {}) => daemonCallWithResult('support_abandon', params),
purchase_list: (params = {}) => daemonCallWithResult('purchase_list', params), purchase_list: (params = {}) => daemonCallWithResult('purchase_list', params),
txo_list: (params = {}) => daemonCallWithResult('txo_list', params),
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),

View file

@ -4,7 +4,7 @@ const channelNameMinLength = 1;
const claimIdMaxLength = 40; const claimIdMaxLength = 40;
// see https://spec.lbry.com/#urls // see https://spec.lbry.com/#urls
export const regexInvalidURI = /[ =&#:$@%?;/\\"<>%{}|^~[\]`\u{0000}-\u{0008}\u{000b}-\u{000c}\u{000e}-\u{001F}\u{D800}-\u{DFFF}\u{FFFE}-\u{FFFF}]/u; export const regexInvalidURI = /[ =&#:$@%?;/\\"<>%\{\}|^~[\]`\u{0000}-\u{0008}\u{000b}-\u{000c}\u{000e}-\u{001F}\u{D800}-\u{DFFF}\u{FFFE}-\u{FFFF}]/u;
export const regexAddress = /^(b|r)(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/; export const regexAddress = /^(b|r)(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/;
const regexPartProtocol = '^((?:lbry://)?)'; const regexPartProtocol = '^((?:lbry://)?)';
const regexPartStreamOrChannelName = '([^:$#/]*)'; const regexPartStreamOrChannelName = '([^:$#/]*)';
@ -12,11 +12,6 @@ const regexPartModifierSeparator = '([:$#]?)([^/]*)';
const queryStringBreaker = '^([\\S]+)([?][\\S]*)'; const queryStringBreaker = '^([\\S]+)([?][\\S]*)';
const separateQuerystring = new RegExp(queryStringBreaker); const separateQuerystring = new RegExp(queryStringBreaker);
const MOD_SEQUENCE_SEPARATOR = '*';
const MOD_CLAIM_ID_SEPARATOR_OLD = '#';
const MOD_CLAIM_ID_SEPARATOR = ':';
const MOD_BID_POSITION_SEPARATOR = '$';
/** /**
* Parses a LBRY name into its component parts. Throws errors with user-friendly * Parses a LBRY name into its component parts. Throws errors with user-friendly
* messages for invalid names. * messages for invalid names.
@ -34,7 +29,7 @@ const MOD_BID_POSITION_SEPARATOR = '$';
* - secondaryBidPosition (int, if present) * - secondaryBidPosition (int, if present)
*/ */
export function parseURI(url: string, requireProto: boolean = false): LbryUrlObj { export function parseURI(URL: string, requireProto: boolean = false): LbryUrlObj {
// Break into components. Empty sub-matches are converted to null // Break into components. Empty sub-matches are converted to null
const componentsRegex = new RegExp( const componentsRegex = new RegExp(
@ -47,12 +42,12 @@ export function parseURI(url: string, requireProto: boolean = false): LbryUrlObj
); );
// chop off the querystring first // chop off the querystring first
let QSStrippedURL, qs; let QSStrippedURL, qs;
const qsRegexResult = separateQuerystring.exec(url); const qsRegexResult = separateQuerystring.exec(URL);
if (qsRegexResult) { if (qsRegexResult) {
[QSStrippedURL, qs] = qsRegexResult.slice(1).map(match => match || null); [QSStrippedURL, qs] = qsRegexResult.slice(1).map(match => match || null);
} }
const cleanURL = QSStrippedURL || url; const cleanURL = QSStrippedURL || URL;
const regexMatch = componentsRegex.exec(cleanURL) || []; const regexMatch = componentsRegex.exec(cleanURL) || [];
const [proto, ...rest] = regexMatch.slice(1).map(match => match || null); const [proto, ...rest] = regexMatch.slice(1).map(match => match || null);
const path = rest.join(''); const path = rest.join('');
@ -80,7 +75,7 @@ export function parseURI(url: string, requireProto: boolean = false): LbryUrlObj
rest.forEach(urlPiece => { rest.forEach(urlPiece => {
if (urlPiece && urlPiece.includes(' ')) { if (urlPiece && urlPiece.includes(' ')) {
throw new Error(__('URL can not include a space')); console.error('URL can not include a space');
} }
}); });
@ -149,11 +144,11 @@ function parseURIModifier(modSeperator: ?string, modValue: ?string) {
throw new Error(__(`No modifier provided after separator %modSeperator%.`, { modSeperator })); throw new Error(__(`No modifier provided after separator %modSeperator%.`, { modSeperator }));
} }
if (modSeperator === MOD_CLAIM_ID_SEPARATOR || MOD_CLAIM_ID_SEPARATOR_OLD) { if (modSeperator === '#') {
claimId = modValue; claimId = modValue;
} else if (modSeperator === MOD_SEQUENCE_SEPARATOR) { } else if (modSeperator === ':') {
claimSequence = modValue; claimSequence = modValue;
} else if (modSeperator === MOD_BID_POSITION_SEPARATOR) { } else if (modSeperator === '$') {
bidPosition = modValue; bidPosition = modValue;
} }
} }
@ -325,22 +320,3 @@ export function convertToShareLink(URL: string) {
'https://open.lbry.com/' 'https://open.lbry.com/'
); );
} }
export function splitBySeparator(uri: string) {
const protocolLength = 7;
return uri.startsWith('lbry://') ? uri.slice(protocolLength).split(/[#:*]/) : uri.split(/#:\*\$/);
}
export function isURIEqual(uriA: string, uriB: string) {
const parseA = parseURI(normalizeURI(uriA));
const parseB = parseURI(normalizeURI(uriB));
if (parseA.isChannel) {
if (parseB.isChannel && parseA.channelClaimId === parseB.channelClaimId) {
return true;
}
} else if (parseA.streamClaimId === parseB.streamClaimId) {
return true;
} else {
return false;
}
}

View file

@ -10,33 +10,15 @@ import {
selectClaimsByUri, selectClaimsByUri,
selectMyChannelClaims, selectMyChannelClaims,
selectPendingIds, selectPendingIds,
selectPendingClaimsById,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { doFetchTxoPage } from 'redux/actions/wallet'; import { doFetchTxoPage } from 'redux/actions/wallet';
import { selectSupportsByOutpoint } from 'redux/selectors/wallet'; import { selectSupportsByOutpoint } from 'redux/selectors/wallet';
import { creditsToString } from 'util/format-credits'; import { creditsToString } from 'util/format-credits';
import { batchActions } from 'util/batch-actions'; import { batchActions } from 'util/batch-actions';
import { createNormalizedClaimSearchKey } from 'util/claim'; import { createNormalizedClaimSearchKey } from 'util/claim';
import { PAGE_SIZE } from 'constants/claim'; import { PAGE_SIZE } from 'constants/claim';
import {
selectPendingCollections,
makeSelectClaimIdsForCollectionId,
} from 'redux/selectors/collections';
import {
doFetchItemsInCollection,
doFetchItemsInCollections,
doCollectionDelete,
} from 'redux/actions/collections';
let onChannelConfirmCallback; export function doResolveUris(uris: Array<string>, returnCachedClaims: boolean = false) {
let checkPendingInterval;
export function doResolveUris(
uris: Array<string>,
returnCachedClaims: boolean = false,
resolveReposts: boolean = true
) {
return (dispatch: Dispatch, getState: GetState) => { return (dispatch: Dispatch, getState: GetState) => {
const normalizedUris = uris.map(normalizeURI); const normalizedUris = uris.map(normalizeURI);
const state = getState(); const state = getState();
@ -72,49 +54,28 @@ export function doResolveUris(
stream: ?StreamClaim, stream: ?StreamClaim,
channel: ?ChannelClaim, channel: ?ChannelClaim,
claimsInChannel: ?number, claimsInChannel: ?number,
collection: ?CollectionClaim,
}, },
} = {}; } = {};
const collectionIds: Array<string> = []; return Lbry.resolve({ urls: urisToResolve, ...options }).then((result: ResolveResponse) => {
Object.entries(result).forEach(([uri, uriResolveInfo]) => {
return Lbry.resolve({ urls: urisToResolve, ...options }).then(
async(result: ResolveResponse) => {
let repostedResults = {};
const repostsToResolve = [];
const fallbackResolveInfo = { const fallbackResolveInfo = {
stream: null, stream: null,
claimsInChannel: null, claimsInChannel: null,
channel: null, channel: null,
}; };
function processResult(result, resolveInfo = {}, checkReposts = false) {
Object.entries(result).forEach(([uri, uriResolveInfo]) => {
// Flow has terrible Object.entries support // Flow has terrible Object.entries support
// https://github.com/facebook/flow/issues/2221 // https://github.com/facebook/flow/issues/2221
if (uriResolveInfo) { if (uriResolveInfo) {
if (uriResolveInfo.error) { if (uriResolveInfo.error) {
// $FlowFixMe
resolveInfo[uri] = { ...fallbackResolveInfo }; resolveInfo[uri] = { ...fallbackResolveInfo };
} else { } else {
if (checkReposts) {
if (uriResolveInfo.reposted_claim) {
// $FlowFixMe
const repostUrl = uriResolveInfo.reposted_claim.permanent_url;
if (!resolvingUris.includes(repostUrl)) {
repostsToResolve.push(repostUrl);
}
}
}
let result = {}; let result = {};
if (uriResolveInfo.value_type === 'channel') { if (uriResolveInfo.value_type === 'channel') {
result.channel = uriResolveInfo; result.channel = uriResolveInfo;
// $FlowFixMe // $FlowFixMe
result.claimsInChannel = uriResolveInfo.meta.claims_in_channel; result.claimsInChannel = uriResolveInfo.meta.claims_in_channel;
} else if (uriResolveInfo.value_type === 'collection') {
result.collection = uriResolveInfo;
// $FlowFixMe
collectionIds.push(uriResolveInfo.claim_id);
} else { } else {
result.stream = uriResolveInfo; result.stream = uriResolveInfo;
if (uriResolveInfo.signing_channel) { if (uriResolveInfo.signing_channel) {
@ -130,30 +91,13 @@ export function doResolveUris(
} }
} }
}); });
}
processResult(result, resolveInfo, resolveReposts);
if (repostsToResolve.length) {
dispatch({
type: ACTIONS.RESOLVE_URIS_STARTED,
data: { uris: repostsToResolve, debug: 'reposts' },
});
repostedResults = await Lbry.resolve({ urls: repostsToResolve, ...options });
}
processResult(repostedResults, resolveInfo);
dispatch({ dispatch({
type: ACTIONS.RESOLVE_URIS_COMPLETED, type: ACTIONS.RESOLVE_URIS_COMPLETED,
data: { resolveInfo }, data: { resolveInfo },
}); });
if (collectionIds.length) {
dispatch(doFetchItemsInCollections({ collectionIds: collectionIds, pageSize: 5 }));
}
return result; return result;
} });
);
}; };
} }
@ -164,24 +108,18 @@ export function doResolveUri(uri: string) {
export function doFetchClaimListMine( export function doFetchClaimListMine(
page: number = 1, page: number = 1,
pageSize: number = 99999, pageSize: number = 99999,
resolve: boolean = true, resolve: boolean = true
filterBy: Array<string> = []
) { ) {
return (dispatch: Dispatch) => { return (dispatch: Dispatch) => {
dispatch({ dispatch({
type: ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED, type: ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED,
}); });
let claimTypes = ['stream', 'repost'];
if (filterBy && filterBy.length !== 0) {
claimTypes = claimTypes.filter(t => filterBy.includes(t));
}
// $FlowFixMe // $FlowFixMe
Lbry.claim_list({ Lbry.claim_list({
page: page, page: page,
page_size: pageSize, page_size: pageSize,
claim_type: claimTypes, claim_type: ['stream', 'repost'],
resolve, resolve,
}).then((result: StreamListResponse) => { }).then((result: StreamListResponse) => {
dispatch({ dispatch({
@ -407,7 +345,7 @@ export function doClearChannelErrors() {
}; };
} }
export function doCreateChannel(name: string, amount: number, optionalParams: any, onConfirm: any) { export function doCreateChannel(name: string, amount: number, optionalParams: any, cb: any) {
return (dispatch: Dispatch) => { return (dispatch: Dispatch) => {
dispatch({ dispatch({
type: ACTIONS.CREATE_CHANNEL_STARTED, type: ACTIONS.CREATE_CHANNEL_STARTED,
@ -423,8 +361,7 @@ export function doCreateChannel(name: string, amount: number, optionalParams: an
description?: string, description?: string,
website_url?: string, website_url?: string,
email?: string, email?: string,
tags?: Array<Tag>, tags?: Array<string>,
languages?: Array<string>,
} = { } = {
name, name,
bid: creditsToString(amount), bid: creditsToString(amount),
@ -453,9 +390,6 @@ export function doCreateChannel(name: string, amount: number, optionalParams: an
if (optionalParams.tags) { if (optionalParams.tags) {
createParams.tags = optionalParams.tags.map(tag => tag.name); createParams.tags = optionalParams.tags.map(tag => tag.name);
} }
if (optionalParams.languages) {
createParams.languages = optionalParams.languages;
}
} }
return ( return (
@ -474,7 +408,7 @@ export function doCreateChannel(name: string, amount: number, optionalParams: an
claims: [channelClaim], claims: [channelClaim],
}, },
}); });
dispatch(doCheckPendingClaims(onConfirm)); dispatch(doCheckPendingClaims(cb));
return channelClaim; return channelClaim;
}) })
.catch(error => { .catch(error => {
@ -507,7 +441,7 @@ export function doUpdateChannel(params: any, cb: any) {
email: params.email, email: params.email,
tags: [], tags: [],
replace: true, replace: true,
languages: params.languages || [], languages: [],
locations: [], locations: [],
blocking: true, blocking: true,
}; };
@ -517,10 +451,15 @@ export function doUpdateChannel(params: any, cb: any) {
} }
// we'll need to remove these once we add locations/channels to channel page edit/create options // we'll need to remove these once we add locations/channels to channel page edit/create options
if (channelClaim && channelClaim.value && channelClaim.value.locations) { if (channelClaim && channelClaim.value && channelClaim.value.locations) {
updateParams.locations = channelClaim.value.locations; updateParams.locations = channelClaim.value.locations;
} }
if (channelClaim && channelClaim.value && channelClaim.value.languages) {
updateParams.languages = channelClaim.value.languages;
}
return Lbry.channel_update(updateParams) return Lbry.channel_update(updateParams)
.then((result: ChannelUpdateResponse) => { .then((result: ChannelUpdateResponse) => {
const channelClaim = result.outputs[0]; const channelClaim = result.outputs[0];
@ -554,7 +493,7 @@ export function doImportChannel(certificate: string) {
}); });
return Lbry.channel_import({ channel_data: certificate }) return Lbry.channel_import({ channel_data: certificate })
.then(() => { .then((result: string) => {
dispatch({ dispatch({
type: ACTIONS.IMPORT_CHANNEL_COMPLETED, type: ACTIONS.IMPORT_CHANNEL_COMPLETED,
}); });
@ -596,54 +535,17 @@ export function doFetchChannelListMine(
}; };
} }
export function doFetchCollectionListMine(page: number = 1, pageSize: number = 99999) {
return (dispatch: Dispatch) => {
dispatch({
type: ACTIONS.FETCH_COLLECTION_LIST_STARTED,
});
const callback = (response: CollectionListResponse) => {
const { items } = response;
dispatch({
type: ACTIONS.FETCH_COLLECTION_LIST_COMPLETED,
data: { claims: items },
});
dispatch(
doFetchItemsInCollections({
collectionIds: items.map(claim => claim.claim_id),
page_size: 5,
})
);
};
const failure = error => {
dispatch({
type: ACTIONS.FETCH_COLLECTION_LIST_FAILED,
data: error,
});
};
Lbry.collection_list({ page, page_size: pageSize, resolve_claims: 1, resolve: true }).then(
callback,
failure
);
};
}
export function doClaimSearch( export function doClaimSearch(
options: { options: {
page_size: number, page_size: number,
page: number, page: number,
no_totals?: boolean, no_totals: boolean,
any_tags?: Array<string>, any_tags?: Array<string>,
claim_ids?: Array<string>,
channel_ids?: Array<string>, channel_ids?: Array<string>,
not_channel_ids?: Array<string>, not_channel_ids?: Array<string>,
not_tags?: Array<string>, not_tags?: Array<string>,
order_by?: Array<string>, order_by?: Array<string>,
release_time?: string, release_time?: string,
has_source?: boolean,
has_no_souce?: boolean,
} = { } = {
no_totals: true, no_totals: true,
page_size: 10, page_size: 10,
@ -651,7 +553,7 @@ export function doClaimSearch(
} }
) { ) {
const query = createNormalizedClaimSearchKey(options); const query = createNormalizedClaimSearchKey(options);
return async(dispatch: Dispatch) => { return (dispatch: Dispatch) => {
dispatch({ dispatch({
type: ACTIONS.CLAIM_SEARCH_STARTED, type: ACTIONS.CLAIM_SEARCH_STARTED,
data: { query: query }, data: { query: query },
@ -675,7 +577,6 @@ export function doClaimSearch(
pageSize: options.page_size, pageSize: options.page_size,
}, },
}); });
return resolveInfo;
}; };
const failure = err => { const failure = err => {
@ -684,10 +585,9 @@ export function doClaimSearch(
data: { query }, data: { query },
error: err, error: err,
}); });
return false;
}; };
return await Lbry.claim_search({ Lbry.claim_search({
...options, ...options,
include_purchase_receipt: true, include_purchase_receipt: true,
}).then(success, failure); }).then(success, failure);
@ -695,7 +595,8 @@ export function doClaimSearch(
} }
export function doRepost(options: StreamRepostOptions) { export function doRepost(options: StreamRepostOptions) {
return (dispatch: Dispatch): Promise<any> => { return (dispatch: Dispatch) => {
// $FlowFixMe
return new Promise(resolve => { return new Promise(resolve => {
dispatch({ dispatch({
type: ACTIONS.CLAIM_REPOST_STARTED, type: ACTIONS.CLAIM_REPOST_STARTED,
@ -710,12 +611,6 @@ export function doRepost(options: StreamRepostOptions) {
repostClaim, repostClaim,
}, },
}); });
dispatch({
type: ACTIONS.UPDATE_PENDING_CLAIMS,
data: {
claims: [repostClaim],
},
});
dispatch(doFetchClaimListMine(1, 10)); dispatch(doFetchClaimListMine(1, 10));
resolve(repostClaim); resolve(repostClaim);
@ -735,209 +630,6 @@ export function doRepost(options: StreamRepostOptions) {
}; };
} }
export function doCollectionPublish(
options: {
name: string,
bid: string,
blocking: true,
title?: string,
channel_id?: string,
thumbnail_url?: string,
description?: string,
tags?: Array<Tag>,
languages?: Array<string>,
claims: Array<string>,
},
localId: string
) {
return (dispatch: Dispatch): Promise<any> => {
// $FlowFixMe
const params: {
name: string,
bid: string,
channel_id?: string,
blocking?: true,
title?: string,
thumbnail_url?: string,
description?: string,
tags?: Array<string>,
languages?: Array<string>,
claims: Array<string>,
} = {
name: options.name,
bid: creditsToString(options.bid),
title: options.title,
thumbnail_url: options.thumbnail_url,
description: options.description,
tags: [],
languages: options.languages || [],
locations: [],
blocking: true,
claims: options.claims,
};
if (options.tags) {
params['tags'] = options.tags.map(tag => tag.name);
}
if (options.channel_id) {
params['channel_id'] = options.channel_id;
}
return new Promise(resolve => {
dispatch({
type: ACTIONS.COLLECTION_PUBLISH_STARTED,
});
function success(response) {
const collectionClaim = response.outputs[0];
dispatch(
batchActions(
{
type: ACTIONS.COLLECTION_PUBLISH_COMPLETED,
data: { claimId: collectionClaim.claim_id },
},
// move unpublished collection to pending collection with new publish id
// recent publish won't resolve this second. handle it in checkPending
{
type: ACTIONS.UPDATE_PENDING_CLAIMS,
data: {
claims: [collectionClaim],
},
}
)
);
dispatch({
type: ACTIONS.COLLECTION_PENDING,
data: { localId: localId, claimId: collectionClaim.claim_id },
});
dispatch(doCheckPendingClaims());
dispatch(doFetchCollectionListMine(1, 10));
return resolve(collectionClaim);
}
function failure(error) {
dispatch({
type: ACTIONS.COLLECTION_PUBLISH_FAILED,
data: {
error: error.message,
},
});
}
return Lbry.collection_create(params).then(success, failure);
});
};
}
export function doCollectionPublishUpdate(
options: {
bid?: string,
blocking?: true,
title?: string,
thumbnail_url?: string,
description?: string,
claim_id: string,
tags?: Array<Tag>,
languages?: Array<string>,
claims?: Array<string>,
channel_id?: string,
},
isBackgroundUpdate?: boolean
) {
return (dispatch: Dispatch, getState: GetState): Promise<any> => {
// TODO: implement one click update
const updateParams: {
bid?: string,
blocking?: true,
title?: string,
thumbnail_url?: string,
channel_id?: string,
description?: string,
claim_id: string,
tags?: Array<string>,
languages?: Array<string>,
claims?: Array<string>,
clear_claims: boolean,
replace?: boolean,
} = isBackgroundUpdate
? {
blocking: true,
claim_id: options.claim_id,
clear_claims: true,
}
: {
bid: creditsToString(options.bid),
title: options.title,
thumbnail_url: options.thumbnail_url,
description: options.description,
tags: [],
languages: options.languages || [],
locations: [],
blocking: true,
claim_id: options.claim_id,
clear_claims: true,
replace: true,
};
if (isBackgroundUpdate && updateParams.claim_id) {
const state = getState();
updateParams['claims'] = makeSelectClaimIdsForCollectionId(updateParams.claim_id)(state);
} else if (options.claims) {
updateParams['claims'] = options.claims;
}
if (options.tags) {
updateParams['tags'] = options.tags.map(tag => tag.name);
}
if (options.channel_id) {
updateParams['channel_id'] = options.channel_id;
}
return new Promise(resolve => {
dispatch({
type: ACTIONS.COLLECTION_PUBLISH_UPDATE_STARTED,
});
function success(response) {
const collectionClaim = response.outputs[0];
dispatch({
type: ACTIONS.COLLECTION_PUBLISH_UPDATE_COMPLETED,
data: {
collectionClaim,
},
});
dispatch({
type: ACTIONS.COLLECTION_PENDING,
data: { claimId: collectionClaim.claim_id },
});
dispatch({
type: ACTIONS.UPDATE_PENDING_CLAIMS,
data: {
claims: [collectionClaim],
},
});
dispatch(doCheckPendingClaims());
return resolve(collectionClaim);
}
function failure(error) {
dispatch({
type: ACTIONS.COLLECTION_PUBLISH_UPDATE_FAILED,
data: {
error: error.message,
},
});
}
return Lbry.collection_update(updateParams).then(success, failure);
});
};
}
export function doCheckPublishNameAvailability(name: string) { export function doCheckPublishNameAvailability(name: string) {
return (dispatch: Dispatch) => { return (dispatch: Dispatch) => {
dispatch({ dispatch({
@ -1000,71 +692,47 @@ export function doPurchaseList(page: number = 1, pageSize: number = PAGE_SIZE) {
}; };
} }
export const doCheckPendingClaims = (onChannelConfirmed: Function) => ( export const doCheckPendingClaims = (onConfirmed: Function) => (
dispatch: Dispatch, dispatch: Dispatch,
getState: GetState getState: GetState
) => { ) => {
if (onChannelConfirmed) { let claimCheckInterval;
onChannelConfirmCallback = onChannelConfirmed;
} const checkClaimList = () => {
clearInterval(checkPendingInterval);
const checkTxoList = () => {
const state = getState(); const state = getState();
const pendingById = Object.assign({}, selectPendingClaimsById(state)); const pendingIdSet = new Set(selectPendingIds(state));
const pendingTxos = (Object.values(pendingById): any).map(p => p.txid); Lbry.claim_list({ page: 1, page_size: 10 })
// use collections
const pendingCollections = selectPendingCollections(state);
if (pendingTxos.length) {
Lbry.txo_list({ txid: pendingTxos })
.then(result => { .then(result => {
const txos = result.items; const claims = result.items;
const idsToConfirm = []; const claimsToConfirm = [];
txos.forEach(txo => { claims.forEach(claim => {
if (txo.claim_id && txo.confirmations > 0) { const { claim_id: claimId } = claim;
idsToConfirm.push(txo.claim_id); if (claim.confirmations > 0 && pendingIdSet.has(claimId)) {
delete pendingById[txo.claim_id]; pendingIdSet.delete(claimId);
claimsToConfirm.push(claim);
if (onConfirmed) {
onConfirmed(claim);
}
} }
}); });
return { idsToConfirm, pendingById }; if (claimsToConfirm.length) {
})
.then(results => {
const { idsToConfirm, pendingById } = results;
if (idsToConfirm.length) {
return Lbry.claim_list({ claim_id: idsToConfirm, resolve: true }).then(results => {
const claims = results.items;
const collectionIds = claims
.filter(c => c.value_type === 'collection')
.map(c => c.claim_id);
dispatch({ dispatch({
type: ACTIONS.UPDATE_CONFIRMED_CLAIMS, type: ACTIONS.UPDATE_CONFIRMED_CLAIMS,
data: { data: {
claims: claims, claims: claimsToConfirm,
pending: pendingById,
}, },
}); });
if (collectionIds.length) { }
dispatch( return pendingIdSet.size;
doFetchItemsInCollections({
collectionIds,
}) })
); .then(len => {
} if (!len) {
const channelClaims = claims.filter(claim => claim.value_type === 'channel'); clearInterval(claimCheckInterval);
if (channelClaims.length && onChannelConfirmCallback) {
channelClaims.forEach(claim => onChannelConfirmCallback(claim));
}
if (Object.keys(pendingById).length === 0) {
clearInterval(checkPendingInterval);
} }
}); });
}
});
} else {
clearInterval(checkPendingInterval);
}
}; };
// do something with onConfirmed (typically get blocklist for channel)
checkPendingInterval = setInterval(() => { claimCheckInterval = setInterval(() => {
checkTxoList(); checkClaimList();
}, 30000); }, 30000);
}; };

View file

@ -1,495 +0,0 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import { v4 as uuid } from 'uuid';
import Lbry from 'lbry';
import { doClaimSearch, doAbandonClaim } from 'redux/actions/claims';
import { makeSelectClaimForClaimId } from 'redux/selectors/claims';
import {
makeSelectCollectionForId,
// makeSelectPublishedCollectionForId, // for "save" or "copy" action
makeSelectMyPublishedCollectionForId,
makeSelectPublishedCollectionForId,
makeSelectUnpublishedCollectionForId,
makeSelectEditedCollectionForId,
} from 'redux/selectors/collections';
import * as COLS from 'constants/collections';
const getTimestamp = () => {
return Math.floor(Date.now() / 1000);
};
const FETCH_BATCH_SIZE = 50;
export const doLocalCollectionCreate = (
name: string,
collectionItems: Array<string>,
type: string,
sourceId: string
) => (dispatch: Dispatch) => {
return dispatch({
type: ACTIONS.COLLECTION_NEW,
data: {
entry: {
id: uuid(), // start with a uuid, this becomes a claimId after publish
name: name,
updatedAt: getTimestamp(),
items: collectionItems || [],
sourceId: sourceId,
type: type,
},
},
});
};
export const doCollectionDelete = (id: string, colKey: ?string = undefined) => (
dispatch: Dispatch,
getState: GetState
) => {
const state = getState();
const claim = makeSelectClaimForClaimId(id)(state);
const collectionDelete = () =>
dispatch({
type: ACTIONS.COLLECTION_DELETE,
data: {
id: id,
collectionKey: colKey,
},
});
if (claim && !colKey) {
// could support "abandon, but keep" later
const { txid, nout } = claim;
return dispatch(doAbandonClaim(txid, nout, collectionDelete));
}
return collectionDelete();
};
// Given a collection, save its collectionId to be resolved and displayed in Library
// export const doCollectionSave = (
// id: string,
// ) => (dispatch: Dispatch) => {
// return dispatch({
// type: ACTIONS.COLLECTION_SAVE,
// data: {
// id: id,
// },
// });
// };
// Given a collection and name, copy it to a local private collection with a name
// export const doCollectionCopy = (
// id: string,
// ) => (dispatch: Dispatch) => {
// return dispatch({
// type: ACTIONS.COLLECTION_COPY,
// data: {
// id: id,
// },
// });
// };
export const doFetchItemsInCollections = (
resolveItemsOptions: {
collectionIds: Array<string>,
pageSize?: number,
},
resolveStartedCallback?: () => void
) => async(dispatch: Dispatch, getState: GetState) => {
/*
1) make sure all the collection claims are loaded into claims reducer, search/resolve if necessary.
2) get the item claims for each
3) format and make sure they're in the order as in the claim
4) Build the collection objects and update collections reducer
5) Update redux claims reducer
*/
let state = getState();
const { collectionIds, pageSize } = resolveItemsOptions;
dispatch({
type: ACTIONS.COLLECTION_ITEMS_RESOLVE_STARTED,
data: { ids: collectionIds },
});
if (resolveStartedCallback) resolveStartedCallback();
const collectionIdsToSearch = collectionIds.filter(claimId => !state.claims.byId[claimId]);
if (collectionIdsToSearch.length) {
await dispatch(doClaimSearch({ claim_ids: collectionIdsToSearch, page: 1, page_size: 9999 }));
}
const stateAfterClaimSearch = getState();
async function fetchItemsForCollectionClaim(claim: CollectionClaim, pageSize?: number) {
const totalItems = claim.value.claims && claim.value.claims.length;
const claimId = claim.claim_id;
const itemOrder = claim.value.claims;
const sortResults = (items: Array<Claim>, claimList) => {
const newItems: Array<Claim> = [];
claimList.forEach(id => {
const index = items.findIndex(i => i.claim_id === id);
if (index >= 0) {
newItems.push(items[index]);
}
});
/*
This will return newItems[] of length less than total_items below
if one or more of the claims has been abandoned. That's ok for now.
*/
return newItems;
};
const mergeBatches = (
arrayOfResults: Array<{ items: Array<Claim>, total_items: number }>,
claimList: Array<string>
) => {
const mergedResults: { items: Array<Claim>, total_items: number } = {
items: [],
total_items: 0,
};
arrayOfResults.forEach(result => {
mergedResults.items = mergedResults.items.concat(result.items);
mergedResults.total_items = result.total_items;
});
mergedResults.items = sortResults(mergedResults.items, claimList);
return mergedResults;
};
try {
const batchSize = pageSize || FETCH_BATCH_SIZE;
const batches: Array<Promise<any>> = [];
for (let i = 0; i < Math.ceil(totalItems / batchSize); i++) {
batches[i] = Lbry.claim_search({
claim_ids: claim.value.claims,
page: i + 1,
page_size: batchSize,
no_totals: true,
});
}
const itemsInBatches = await Promise.all(batches);
const result = mergeBatches(itemsInBatches, itemOrder);
// $FlowFixMe
const itemsById: { claimId: string, items?: ?Array<GenericClaim> } = { claimId: claimId };
if (result.items) {
itemsById.items = result.items;
} else {
itemsById.items = null;
}
return itemsById;
} catch (e) {
return {
claimId: claimId,
items: null,
};
}
}
function formatForClaimActions(resultClaimsByUri) {
const formattedClaims = {};
Object.entries(resultClaimsByUri).forEach(([uri, uriResolveInfo]) => {
// Flow has terrible Object.entries support
// https://github.com/facebook/flow/issues/2221
if (uriResolveInfo) {
let result = {};
if (uriResolveInfo.value_type === 'channel') {
result.channel = uriResolveInfo;
// $FlowFixMe
result.claimsInChannel = uriResolveInfo.meta.claims_in_channel;
// ALSO SKIP COLLECTIONS
} else if (uriResolveInfo.value_type === 'collection') {
result.collection = uriResolveInfo;
} else {
result.stream = uriResolveInfo;
if (uriResolveInfo.signing_channel) {
result.channel = uriResolveInfo.signing_channel;
result.claimsInChannel =
(uriResolveInfo.signing_channel.meta &&
uriResolveInfo.signing_channel.meta.claims_in_channel) ||
0;
}
}
// $FlowFixMe
formattedClaims[uri] = result;
}
});
return formattedClaims;
}
const invalidCollectionIds = [];
const promisedCollectionItemFetches = [];
collectionIds.forEach(collectionId => {
const claim = makeSelectClaimForClaimId(collectionId)(stateAfterClaimSearch);
if (!claim) {
invalidCollectionIds.push(collectionId);
} else {
promisedCollectionItemFetches.push(fetchItemsForCollectionClaim(claim, pageSize));
}
});
// $FlowFixMe
const collectionItemsById: Array<{
claimId: string,
items: ?Array<GenericClaim>,
}> = await Promise.all(promisedCollectionItemFetches);
const newCollectionObjectsById = {};
const resolvedItemsByUrl = {};
collectionItemsById.forEach(entry => {
// $FlowFixMe
const collectionItems: Array<any> = entry.items;
const collectionId = entry.claimId;
if (collectionItems) {
const claim = makeSelectClaimForClaimId(collectionId)(stateAfterClaimSearch);
const editedCollection = makeSelectEditedCollectionForId(collectionId)(stateAfterClaimSearch);
const { name, timestamp, value } = claim || {};
const { title } = value;
const valueTypes = new Set();
const streamTypes = new Set();
let newItems = [];
let isPlaylist;
if (collectionItems) {
collectionItems.forEach(collectionItem => {
newItems.push(collectionItem.permanent_url);
valueTypes.add(collectionItem.value_type);
if (collectionItem.value.stream_type) {
streamTypes.add(collectionItem.value.stream_type);
}
resolvedItemsByUrl[collectionItem.canonical_url] = collectionItem;
});
isPlaylist =
valueTypes.size === 1 &&
valueTypes.has('stream') &&
((streamTypes.size === 1 && (streamTypes.has('audio') || streamTypes.has('video'))) ||
(streamTypes.size === 2 && (streamTypes.has('audio') && streamTypes.has('video'))));
}
newCollectionObjectsById[collectionId] = {
items: newItems,
id: collectionId,
name: title || name,
itemCount: claim.value.claims.length,
type: isPlaylist ? 'playlist' : 'collection',
updatedAt: timestamp,
};
if (editedCollection && timestamp > editedCollection['updatedAt']) {
dispatch({
type: ACTIONS.COLLECTION_DELETE,
data: {
id: collectionId,
collectionKey: 'edited',
},
});
}
} else {
invalidCollectionIds.push(collectionId);
}
});
const formattedClaimsByUri = formatForClaimActions(collectionItemsById);
dispatch({
type: ACTIONS.RESOLVE_URIS_COMPLETED,
data: { resolveInfo: formattedClaimsByUri },
});
dispatch({
type: ACTIONS.COLLECTION_ITEMS_RESOLVE_COMPLETED,
data: {
resolvedCollections: newCollectionObjectsById,
failedCollectionIds: invalidCollectionIds,
},
});
};
export const doFetchItemsInCollection = (
options: { collectionId: string, pageSize?: number },
cb?: () => void
) => {
const { collectionId, pageSize } = options;
const newOptions: { collectionIds: Array<string>, pageSize?: number } = {
collectionIds: [collectionId],
};
if (pageSize) newOptions.pageSize = pageSize;
return doFetchItemsInCollections(newOptions, cb);
};
export const doCollectionEdit = (collectionId: string, params: CollectionEditParams) => async(
dispatch: Dispatch,
getState: GetState
) => {
const state = getState();
const collection: Collection = makeSelectCollectionForId(collectionId)(state);
const editedCollection: Collection = makeSelectEditedCollectionForId(collectionId)(state);
const unpublishedCollection: Collection = makeSelectUnpublishedCollectionForId(collectionId)(
state
);
const publishedCollection: Collection = makeSelectPublishedCollectionForId(collectionId)(state); // needs to be published only
const generateCollectionItemsFromSearchResult = results => {
return (
Object.values(results)
// $FlowFixMe
.reduce(
(
acc,
cur: {
stream: ?StreamClaim,
channel: ?ChannelClaim,
claimsInChannel: ?number,
collection: ?CollectionClaim,
}
) => {
let url;
if (cur.stream) {
url = cur.stream.permanent_url;
} else if (cur.channel) {
url = cur.channel.permanent_url;
} else if (cur.collection) {
url = cur.collection.permanent_url;
} else {
return acc;
}
acc.push(url);
return acc;
},
[]
)
);
};
if (!collection) {
return dispatch({
type: ACTIONS.COLLECTION_ERROR,
data: {
message: 'collection does not exist',
},
});
}
let currentItems = collection.items ? collection.items.concat() : [];
const { claims: passedClaims, order, claimIds, replace, remove, type } = params;
const collectionType = type || collection.type;
let newItems: Array<?string> = currentItems;
if (passedClaims) {
if (remove) {
const passedUrls = passedClaims.map(claim => claim.permanent_url);
// $FlowFixMe // need this?
newItems = currentItems.filter((item: string) => !passedUrls.includes(item));
} else {
passedClaims.forEach(claim => newItems.push(claim.permanent_url));
}
}
if (claimIds) {
const batches = [];
if (claimIds.length > 50) {
for (let i = 0; i < Math.ceil(claimIds.length / 50); i++) {
batches[i] = claimIds.slice(i * 50, (i + 1) * 50);
}
} else {
batches[0] = claimIds;
}
const resultArray = await Promise.all(
batches.map(batch => {
let options = { claim_ids: batch, page: 1, page_size: 50 };
return dispatch(doClaimSearch(options));
})
);
const searchResults = Object.assign({}, ...resultArray);
if (replace) {
newItems = generateCollectionItemsFromSearchResult(searchResults);
} else {
newItems = currentItems.concat(generateCollectionItemsFromSearchResult(searchResults));
}
}
if (order) {
const [movedItem] = currentItems.splice(order.from, 1);
currentItems.splice(order.to, 0, movedItem);
}
// console.log('p&e', publishedCollection.items, newItems, publishedCollection.items.join(','), newItems.join(','))
if (editedCollection) {
// delete edited if newItems are the same as publishedItems
if (publishedCollection.items.join(',') === newItems.join(',')) {
dispatch({
type: ACTIONS.COLLECTION_DELETE,
data: {
id: collectionId,
collectionKey: 'edited',
},
});
} else {
dispatch({
type: ACTIONS.COLLECTION_EDIT,
data: {
id: collectionId,
collectionKey: 'edited',
collection: {
items: newItems,
id: collectionId,
name: params.name || collection.name,
updatedAt: getTimestamp(),
type: collectionType,
},
},
});
}
} else if (publishedCollection) {
dispatch({
type: ACTIONS.COLLECTION_EDIT,
data: {
id: collectionId,
collectionKey: 'edited',
collection: {
items: newItems,
id: collectionId,
name: params.name || collection.name,
updatedAt: getTimestamp(),
type: collectionType,
},
},
});
} else if (COLS.BUILTIN_LISTS.includes(collectionId)) {
dispatch({
type: ACTIONS.COLLECTION_EDIT,
data: {
id: collectionId,
collectionKey: 'builtin',
collection: {
items: newItems,
id: collectionId,
name: params.name || collection.name,
updatedAt: getTimestamp(),
type: collectionType,
},
},
});
} else if (unpublishedCollection) {
dispatch({
type: ACTIONS.COLLECTION_EDIT,
data: {
id: collectionId,
collectionKey: 'unpublished',
collection: {
items: newItems,
id: collectionId,
name: params.name || collection.name,
updatedAt: getTimestamp(),
type: collectionType,
},
},
});
}
return true;
};

View file

@ -104,10 +104,7 @@ export function doPurchaseUri(
data: { uri, error: `Already fetching uri: ${uri}` }, data: { uri, error: `Already fetching uri: ${uri}` },
}); });
if (onSuccess) { Promise.resolve();
onSuccess(fileInfo);
}
return; return;
} }

View file

@ -1,6 +1,6 @@
// @flow // @flow
import * as ACTIONS from 'constants/action_types'; import * as ACTIONS from 'constants/action_types';
import { v4 as uuid } from 'uuid'; import uuid from 'uuid/v4';
export function doToast(params: ToastParams) { export function doToast(params: ToastParams) {
if (!params) { if (!params) {

View file

@ -21,7 +21,6 @@ export const doResetThumbnailStatus = () => (dispatch: Dispatch) => {
type: ACTIONS.UPDATE_PUBLISH_FORM, type: ACTIONS.UPDATE_PUBLISH_FORM,
data: { data: {
thumbnailPath: '', thumbnailPath: '',
thumbnailError: undefined,
}, },
}); });
@ -69,8 +68,7 @@ export const doUploadThumbnail = (
thumbnailBlob?: File, thumbnailBlob?: File,
fsAdapter?: any, fsAdapter?: any,
fs?: any, fs?: any,
path?: any, path?: any
cb?: (string) => void
) => (dispatch: Dispatch) => { ) => (dispatch: Dispatch) => {
const downMessage = __('Thumbnail upload service may be down, try again later.'); const downMessage = __('Thumbnail upload service may be down, try again later.');
let thumbnail, fileExt, fileName, fileType; let thumbnail, fileExt, fileName, fileType;
@ -98,13 +96,6 @@ export const doUploadThumbnail = (
); );
}; };
dispatch({
type: ACTIONS.UPDATE_PUBLISH_FORM,
data: {
thumbnailError: undefined,
},
});
const doUpload = data => { const doUpload = data => {
return fetch(SPEECH_PUBLISH, { return fetch(SPEECH_PUBLISH, {
method: 'POST', method: 'POST',
@ -113,17 +104,15 @@ export const doUploadThumbnail = (
.then(res => res.text()) .then(res => res.text())
.then(text => (text.length ? JSON.parse(text) : {})) .then(text => (text.length ? JSON.parse(text) : {}))
.then(json => { .then(json => {
if (!json.success) return uploadError(json.message || downMessage); return json.success
if (cb) { ? dispatch({
cb(json.data.serveUrl);
}
return dispatch({
type: ACTIONS.UPDATE_PUBLISH_FORM, type: ACTIONS.UPDATE_PUBLISH_FORM,
data: { data: {
uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE, uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE,
thumbnail: json.data.serveUrl, thumbnail: json.data.serveUrl,
}, },
}); })
: uploadError(json.message || downMessage);
}) })
.catch(err => { .catch(err => {
let message = err.message; let message = err.message;
@ -195,7 +184,6 @@ export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileLis
currency: 'LBC', currency: 'LBC',
}, },
languages, languages,
release_time,
license, license,
license_url: licenseUrl, license_url: licenseUrl,
thumbnail, thumbnail,
@ -211,8 +199,6 @@ export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileLis
description, description,
fee, fee,
languages, languages,
releaseTime: release_time,
releaseTimeEdited: undefined,
thumbnail: thumbnail ? thumbnail.url : null, thumbnail: thumbnail ? thumbnail.url : null,
title, title,
uri, uri,
@ -266,7 +252,6 @@ export const doPublish = (success: Function, fail: Function, preview: Function)
filePath, filePath,
description, description,
language, language,
releaseTimeEdited,
license, license,
licenseUrl, licenseUrl,
useLBRYUploader, useLBRYUploader,
@ -281,10 +266,7 @@ export const doPublish = (success: Function, fail: Function, preview: Function)
tags, tags,
locations, locations,
optimize, optimize,
isLivestreamPublish,
remoteFileUrl,
} = publishData; } = publishData;
// Handle scenario where we have a claim that has the same name as a channel we are publishing with. // Handle scenario where we have a claim that has the same name as a channel we are publishing with.
const myClaimForUriEditing = myClaimForUri && myClaimForUri.name === name ? myClaimForUri : null; const myClaimForUriEditing = myClaimForUri && myClaimForUri.name === name ? myClaimForUri : null;
@ -310,6 +292,7 @@ export const doPublish = (success: Function, fail: Function, preview: Function)
description?: string, description?: string,
channel_id?: string, channel_id?: string,
file_path?: string, file_path?: string,
license_url?: string, license_url?: string,
license?: string, license?: string,
thumbnail_url?: string, thumbnail_url?: string,
@ -322,7 +305,6 @@ export const doPublish = (success: Function, fail: Function, preview: Function)
blocking: boolean, blocking: boolean,
optimize_file?: boolean, optimize_file?: boolean,
preview?: boolean, preview?: boolean,
remote_url?: string,
} = { } = {
name, name,
title, title,
@ -338,9 +320,6 @@ export const doPublish = (success: Function, fail: Function, preview: Function)
// Temporary solution to keep the same publish flow with the new tags api // Temporary solution to keep the same publish flow with the new tags api
// Eventually we will allow users to enter their own tags on publish // Eventually we will allow users to enter their own tags on publish
// `nsfw` will probably be removed // `nsfw` will probably be removed
if (remoteFileUrl) {
publishPayload.remote_url = remoteFileUrl;
}
if (publishingLicense) { if (publishingLicense) {
publishPayload.license = publishingLicense; publishPayload.license = publishingLicense;
@ -359,9 +338,7 @@ export const doPublish = (success: Function, fail: Function, preview: Function)
} }
// Set release time to curret date. On edits, keep original release/transaction time as release_time // Set release time to curret date. On edits, keep original release/transaction time as release_time
if (releaseTimeEdited) { if (myClaimForUriEditing && myClaimForUriEditing.value.release_time) {
publishPayload.release_time = releaseTimeEdited;
} else if (myClaimForUriEditing && myClaimForUriEditing.value.release_time) {
publishPayload.release_time = Number(myClaimForUri.value.release_time); publishPayload.release_time = Number(myClaimForUri.value.release_time);
} else if (myClaimForUriEditing && myClaimForUriEditing.timestamp) { } else if (myClaimForUriEditing && myClaimForUriEditing.timestamp) {
publishPayload.release_time = Number(myClaimForUriEditing.timestamp); publishPayload.release_time = Number(myClaimForUriEditing.timestamp);
@ -388,7 +365,7 @@ export const doPublish = (success: Function, fail: Function, preview: Function)
// Only pass file on new uploads, not metadata only edits. // Only pass file on new uploads, not metadata only edits.
// The sdk will figure it out // The sdk will figure it out
if (filePath && !isLivestreamPublish) publishPayload.file_path = filePath; if (filePath) publishPayload.file_path = filePath;
if (preview) { if (preview) {
publishPayload.preview = true; publishPayload.preview = true;

View file

@ -6,17 +6,11 @@ type SharedData = {
version: '0.1', version: '0.1',
value: { value: {
subscriptions?: Array<string>, subscriptions?: Array<string>,
following?: Array<{ uri: string, notificationsDisabled: boolean }>,
tags?: Array<string>, tags?: Array<string>,
blocked?: Array<string>, blocked?: Array<string>,
coin_swap_codes?: Array<string>,
settings?: any, settings?: any,
app_welcome_version?: number, app_welcome_version?: number,
sharing_3P?: boolean, sharing_3P?: boolean,
unpublishedCollections: CollectionGroup,
editedCollections: CollectionGroup,
builtinCollections: CollectionGroup,
savedCollections: Array<string>,
}, },
}; };
@ -24,32 +18,20 @@ function extractUserState(rawObj: SharedData) {
if (rawObj && rawObj.version === '0.1' && rawObj.value) { if (rawObj && rawObj.version === '0.1' && rawObj.value) {
const { const {
subscriptions, subscriptions,
following,
tags, tags,
blocked, blocked,
coin_swap_codes,
settings, settings,
app_welcome_version, app_welcome_version,
sharing_3P, sharing_3P,
unpublishedCollections,
editedCollections,
builtinCollections,
savedCollections,
} = rawObj.value; } = rawObj.value;
return { return {
...(subscriptions ? { subscriptions } : {}), ...(subscriptions ? { subscriptions } : {}),
...(following ? { following } : {}),
...(tags ? { tags } : {}), ...(tags ? { tags } : {}),
...(blocked ? { blocked } : {}), ...(blocked ? { blocked } : {}),
...(coin_swap_codes ? { coin_swap_codes } : {}),
...(settings ? { settings } : {}), ...(settings ? { settings } : {}),
...(app_welcome_version ? { app_welcome_version } : {}), ...(app_welcome_version ? { app_welcome_version } : {}),
...(sharing_3P ? { sharing_3P } : {}), ...(sharing_3P ? { sharing_3P } : {}),
...(unpublishedCollections ? { unpublishedCollections } : {}),
...(editedCollections ? { editedCollections } : {}),
...(builtinCollections ? { builtinCollections } : {}),
...(savedCollections ? { savedCollections } : {}),
}; };
} }
@ -60,33 +42,21 @@ export function doPopulateSharedUserState(sharedSettings: any) {
return (dispatch: Dispatch) => { return (dispatch: Dispatch) => {
const { const {
subscriptions, subscriptions,
following,
tags, tags,
blocked, blocked,
coin_swap_codes,
settings, settings,
app_welcome_version, app_welcome_version,
sharing_3P, sharing_3P,
unpublishedCollections,
editedCollections,
builtinCollections,
savedCollections,
} = extractUserState(sharedSettings); } = extractUserState(sharedSettings);
dispatch({ dispatch({
type: ACTIONS.USER_STATE_POPULATE, type: ACTIONS.USER_STATE_POPULATE,
data: { data: {
subscriptions, subscriptions,
following,
tags, tags,
blocked, blocked,
coinSwapCodes: coin_swap_codes,
settings, settings,
welcomeVersion: app_welcome_version, welcomeVersion: app_welcome_version,
allowAnalytics: sharing_3P, allowAnalytics: sharing_3P,
unpublishedCollections,
editedCollections,
builtinCollections,
savedCollections,
}, },
}); });
}; };
@ -99,7 +69,6 @@ export function doPreferenceSet(
success: Function, success: Function,
fail: Function fail: Function
) { ) {
return (dispatch: Dispatch) => {
const preference = { const preference = {
type: typeof value, type: typeof value,
version, version,
@ -113,25 +82,16 @@ export function doPreferenceSet(
Lbry.preference_set(options) Lbry.preference_set(options)
.then(() => { .then(() => {
if (success) {
success(preference); success(preference);
}
}) })
.catch(err => { .catch(() => {
dispatch({
type: ACTIONS.SYNC_FATAL_ERROR,
error: err,
});
if (fail) { if (fail) {
fail(); fail();
} }
}); });
};
} }
export function doPreferenceGet(key: string, success: Function, fail?: Function) { export function doPreferenceGet(key: string, success: Function, fail?: Function) {
return (dispatch: Dispatch) => {
const options = { const options = {
key, key,
}; };
@ -146,14 +106,8 @@ export function doPreferenceGet(key: string, success: Function, fail?: Function)
return success(null); return success(null);
}) })
.catch(err => { .catch(err => {
dispatch({
type: ACTIONS.SYNC_FATAL_ERROR,
error: err,
});
if (fail) { if (fail) {
fail(err); fail(err);
} }
}); });
};
} }

24
src/redux/actions/tags.js Normal file
View file

@ -0,0 +1,24 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import Lbry from 'lbry';
export const doToggleTagFollow = (name: string) => ({
type: ACTIONS.TOGGLE_TAG_FOLLOW,
data: {
name,
},
});
export const doAddTag = (name: string) => ({
type: ACTIONS.TAG_ADD,
data: {
name,
},
});
export const doDeleteTag = (name: string) => ({
type: ACTIONS.TAG_DELETE,
data: {
name,
},
});

View file

@ -5,17 +5,13 @@ import {
selectBalance, selectBalance,
selectPendingSupportTransactions, selectPendingSupportTransactions,
selectTxoPageParams, selectTxoPageParams,
selectPendingOtherTransactions,
selectPendingConsolidateTxid,
selectPendingMassClaimTxid,
} from 'redux/selectors/wallet'; } from 'redux/selectors/wallet';
import { creditsToString } from 'util/format-credits'; import { creditsToString } from 'util/format-credits';
import { selectMyClaimsRaw, selectClaimsById } from 'redux/selectors/claims'; import { selectMyClaimsRaw } from 'redux/selectors/claims';
import { doFetchChannelListMine, doFetchClaimListMine, doClaimSearch } from 'redux/actions/claims'; import { doFetchChannelListMine, doFetchClaimListMine } from 'redux/actions/claims';
const FIFTEEN_SECONDS = 15000; const FIFTEEN_SECONDS = 15000;
let walletBalancePromise = null; let walletBalancePromise = null;
export function doUpdateBalance() { export function doUpdateBalance() {
return (dispatch, getState) => { return (dispatch, getState) => {
const { const {
@ -57,12 +53,13 @@ export function doUpdateBalance() {
export function doBalanceSubscribe() { export function doBalanceSubscribe() {
return dispatch => { return dispatch => {
dispatch(doUpdateBalance()); dispatch(doUpdateBalance());
setInterval(() => dispatch(doUpdateBalance()), 10000); setInterval(() => dispatch(doUpdateBalance()), 5000);
}; };
} }
export function doFetchTransactions(page = 1, pageSize = 999999) { export function doFetchTransactions(page = 1, pageSize = 99999) {
return dispatch => { return dispatch => {
dispatch(doFetchSupports());
dispatch({ dispatch({
type: ACTIONS.FETCH_TRANSACTIONS_STARTED, type: ACTIONS.FETCH_TRANSACTIONS_STARTED,
}); });
@ -80,63 +77,24 @@ export function doFetchTransactions(page = 1, pageSize = 999999) {
export function doFetchTxoPage() { export function doFetchTxoPage() {
return (dispatch, getState) => { return (dispatch, getState) => {
const fetchId = Math.random()
.toString(36)
.substr(2, 9);
dispatch({ dispatch({
type: ACTIONS.FETCH_TXO_PAGE_STARTED, type: ACTIONS.FETCH_TXO_PAGE_STARTED,
data: fetchId,
}); });
const state = getState(); const state = getState();
const queryParams = selectTxoPageParams(state); const queryParams = selectTxoPageParams(state);
Lbry.txo_list(queryParams) Lbry.txo_list(queryParams)
.then(res => {
const items = res.items || [];
const claimsById = selectClaimsById(state);
const channelIds = items.reduce((acc, cur) => {
if (
cur.type === 'support' &&
cur.signing_channel &&
!claimsById[cur.signing_channel.channel_id]
) {
acc.push(cur.signing_channel.channel_id);
}
return acc;
}, []);
if (channelIds.length) {
const searchParams = {
page_size: 9999,
page: 1,
no_totals: true,
claim_ids: channelIds,
};
// make sure redux has these channels resolved
dispatch(doClaimSearch(searchParams));
}
return res;
})
.then(res => { .then(res => {
dispatch({ dispatch({
type: ACTIONS.FETCH_TXO_PAGE_COMPLETED, type: ACTIONS.FETCH_TXO_PAGE_COMPLETED,
data: { data: res,
result: res,
fetchId: fetchId,
},
}); });
}) })
.catch(e => { .catch(e => {
dispatch({ dispatch({
type: ACTIONS.FETCH_TXO_PAGE_COMPLETED, type: ACTIONS.FETCH_TXO_PAGE_COMPLETED,
data: { data: e.message,
error: e.message,
fetchId: fetchId,
},
}); });
}); });
}; };
@ -170,74 +128,6 @@ export function doFetchSupports(page = 1, pageSize = 99999) {
}; };
} }
export function doFetchUtxoCounts() {
return async dispatch => {
dispatch({
type: ACTIONS.FETCH_UTXO_COUNT_STARTED,
});
let resultSets = await Promise.all([
Lbry.txo_list({ type: 'other', is_not_spent: true, page: 1, page_size: 1 }),
Lbry.txo_list({ type: 'support', is_not_spent: true, page: 1, page_size: 1 }),
]);
const counts = {};
const paymentCount = resultSets[0]['total_items'];
const supportCount = resultSets[1]['total_items'];
counts['other'] = typeof paymentCount === 'number' ? paymentCount : 0;
counts['support'] = typeof supportCount === 'number' ? supportCount : 0;
dispatch({
type: ACTIONS.FETCH_UTXO_COUNT_COMPLETED,
data: counts,
debug: { resultSets },
});
};
}
export function doUtxoConsolidate() {
return async dispatch => {
dispatch({
type: ACTIONS.DO_UTXO_CONSOLIDATE_STARTED,
});
const results = await Lbry.txo_spend({ type: 'other' });
const result = results[0];
dispatch({
type: ACTIONS.PENDING_CONSOLIDATED_TXOS_UPDATED,
data: { txids: [result.txid] },
});
dispatch({
type: ACTIONS.DO_UTXO_CONSOLIDATE_COMPLETED,
data: { txid: result.txid },
});
dispatch(doCheckPendingTxs());
};
}
export function doTipClaimMass() {
return async dispatch => {
dispatch({
type: ACTIONS.TIP_CLAIM_MASS_STARTED,
});
const results = await Lbry.txo_spend({ type: 'support', is_not_my_input: true });
const result = results[0];
dispatch({
type: ACTIONS.PENDING_CONSOLIDATED_TXOS_UPDATED,
data: { txids: [result.txid] },
});
dispatch({
type: ACTIONS.TIP_CLAIM_MASS_COMPLETED,
data: { txid: result.txid },
});
dispatch(doCheckPendingTxs());
};
}
export function doGetNewAddress() { export function doGetNewAddress() {
return dispatch => { return dispatch => {
dispatch({ dispatch({
@ -348,7 +238,7 @@ export function doSetDraftTransactionAddress(address) {
}; };
} }
export function doSendTip(params, isSupport, successCallback, errorCallback, shouldNotify = true) { export function doSendTip(params, isSupport, successCallback, errorCallback) {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const balance = selectBalance(state); const balance = selectBalance(state);
@ -367,8 +257,7 @@ export function doSendTip(params, isSupport, successCallback, errorCallback, sho
return; return;
} }
const success = response => { const success = () => {
if (shouldNotify) {
dispatch( dispatch(
doToast({ doToast({
message: shouldSupport message: shouldSupport
@ -378,14 +267,13 @@ export function doSendTip(params, isSupport, successCallback, errorCallback, sho
linkTarget: '/wallet', linkTarget: '/wallet',
}) })
); );
}
dispatch({ dispatch({
type: ACTIONS.SUPPORT_TRANSACTION_COMPLETED, type: ACTIONS.SUPPORT_TRANSACTION_COMPLETED,
}); });
if (successCallback) { if (successCallback) {
successCallback(response); successCallback();
} }
}; };
@ -494,7 +382,6 @@ export function doWalletLock() {
}; };
} }
// Collect all tips for a claim
export function doSupportAbandonForClaim(claimId, claimType, keep, preview) { export function doSupportAbandonForClaim(claimId, claimType, keep, preview) {
return dispatch => { return dispatch => {
if (preview) { if (preview) {
@ -515,7 +402,7 @@ export function doSupportAbandonForClaim(claimId, claimType, keep, preview) {
if (!preview) { if (!preview) {
dispatch({ dispatch({
type: ACTIONS.ABANDON_CLAIM_SUPPORT_COMPLETED, type: ACTIONS.ABANDON_CLAIM_SUPPORT_COMPLETED,
data: { claimId, txid: res.txid, effective: res.outputs[0].amount, type: claimType }, data: { claimId, txid: res.txid, effective: res.outputs[0].amount, type: claimType }, // add to pendingSupportTransactions,
}); });
dispatch(doCheckPendingTxs()); dispatch(doCheckPendingTxs());
} }
@ -558,7 +445,6 @@ export function doWalletReconnect() {
}); });
}; };
} }
export function doWalletDecrypt() { export function doWalletDecrypt() {
return dispatch => { return dispatch => {
dispatch({ dispatch({
@ -621,50 +507,35 @@ export function doUpdateBlockHeight() {
export const doCheckPendingTxs = () => (dispatch, getState) => { export const doCheckPendingTxs = () => (dispatch, getState) => {
const state = getState(); const state = getState();
const pendingTxsById = selectPendingSupportTransactions(state); // {} const pendingTxsById = selectPendingSupportTransactions(state); // {}
const pendingOtherTxes = selectPendingOtherTransactions(state); if (!Object.keys(pendingTxsById).length) {
if (!Object.keys(pendingTxsById).length && !pendingOtherTxes.length) {
return; return;
} }
let txCheckInterval; let txCheckInterval;
const checkTxList = () => { const checkTxList = () => {
const state = getState(); const state = getState();
const pendingSupportTxs = selectPendingSupportTransactions(state); // {} const pendingTxs = selectPendingSupportTransactions(state); // {}
const pendingConsolidateTxes = selectPendingOtherTransactions(state);
const pendingConsTxid = selectPendingConsolidateTxid(state);
const pendingMassCLaimTxid = selectPendingMassClaimTxid(state);
const promises = []; const promises = [];
const newPendingTxes = {}; const newPendingTxes = {};
const noLongerPendingConsolidate = [];
const types = new Set([]); const types = new Set([]);
// { claimId: {txid: 123, amount 12.3}, } let changed = false;
const entries = Object.entries(pendingSupportTxs); Object.entries(pendingTxs).forEach(([claim, data]) => {
entries.forEach(([claim, data]) => {
promises.push(Lbry.transaction_show({ txid: data.txid })); promises.push(Lbry.transaction_show({ txid: data.txid }));
types.add(data.type); types.add(data.type);
}); });
if (pendingConsolidateTxes.length) {
pendingConsolidateTxes.forEach(txid => promises.push(Lbry.transaction_show({ txid })));
}
Promise.all(promises).then(txShows => { Promise.all(promises)
let changed = false; .then(txShows => {
txShows.forEach(result => { txShows.forEach(result => {
if (pendingConsolidateTxes.includes(result.txid)) {
if (result.height > 0) {
noLongerPendingConsolidate.push(result.txid);
}
} else {
if (result.height <= 0) { if (result.height <= 0) {
const entries = Object.entries(pendingTxs);
const match = entries.find(entry => entry[1].txid === result.txid); const match = entries.find(entry => entry[1].txid === result.txid);
newPendingTxes[match[0]] = match[1]; newPendingTxes[match[0]] = match[1];
} else { } else {
changed = true; changed = true;
} }
}
}); });
})
.then(() => {
if (changed) { if (changed) {
dispatch({ dispatch({
type: ACTIONS.PENDING_SUPPORTS_UPDATED, type: ACTIONS.PENDING_SUPPORTS_UPDATED,
@ -677,31 +548,12 @@ export const doCheckPendingTxs = () => (dispatch, getState) => {
dispatch(doFetchClaimListMine()); dispatch(doFetchClaimListMine());
} }
} }
if (noLongerPendingConsolidate.length) { if (Object.keys(newPendingTxes).length === 0) clearInterval(txCheckInterval);
if (noLongerPendingConsolidate.includes(pendingConsTxid)) {
dispatch(
doToast({
message: __('Your wallet is finished consolidating'),
})
);
}
if (noLongerPendingConsolidate.includes(pendingMassCLaimTxid)) {
dispatch(
doToast({
message: __('Your tips have been collected'),
})
);
}
dispatch({
type: ACTIONS.PENDING_CONSOLIDATED_TXOS_UPDATED,
data: { txids: noLongerPendingConsolidate, remove: true },
}); });
}
if (!Object.keys(pendingTxsById).length && !pendingOtherTxes.length) { if (!Object.keys(pendingTxsById).length) {
clearInterval(txCheckInterval); clearInterval(txCheckInterval);
} }
});
}; };
txCheckInterval = setInterval(() => { txCheckInterval = setInterval(() => {

View file

@ -2,10 +2,9 @@
import isEqual from 'util/deep-equal'; import isEqual from 'util/deep-equal';
import { doPreferenceSet } from 'redux/actions/sync'; import { doPreferenceSet } from 'redux/actions/sync';
const RUN_PREFERENCES_DELAY_MS = 2000;
const SHARED_PREFERENCE_VERSION = '0.1'; const SHARED_PREFERENCE_VERSION = '0.1';
let oldShared = {}; let oldShared = {};
let timeout;
export const buildSharedStateMiddleware = ( export const buildSharedStateMiddleware = (
actions: Array<string>, actions: Array<string>,
sharedStateFilters: {}, sharedStateFilters: {},
@ -23,10 +22,9 @@ export const buildSharedStateMiddleware = (
if (!actions.includes(action.type) || typeof action === 'function') { if (!actions.includes(action.type) || typeof action === 'function') {
return next(action); return next(action);
} }
clearTimeout(timeout);
const actionResult = next(action); const actionResult = next(action);
// Call `getState` after calling `next` to ensure the state has updated in response to the action // Call `getState` after calling `next` to ensure the state has updated in response to the action
function runPreferences() {
const nextState: { user: any, settings: any } = getState(); const nextState: { user: any, settings: any } = getState();
const syncEnabled = const syncEnabled =
nextState.settings && nextState.settings &&
@ -51,15 +49,13 @@ export const buildSharedStateMiddleware = (
if (!isEqual(oldShared, shared)) { if (!isEqual(oldShared, shared)) {
// only update if the preference changed from last call in the same session // only update if the preference changed from last call in the same session
oldShared = shared; oldShared = shared;
dispatch(doPreferenceSet(preferenceKey, shared, SHARED_PREFERENCE_VERSION)); doPreferenceSet(preferenceKey, shared, SHARED_PREFERENCE_VERSION);
} }
if (sharedStateCb) { if (sharedStateCb) {
// Pass dispatch to the callback to consumers can dispatch actions in response to preference set // Pass dispatch to the callback to consumers can dispatch actions in response to preference set
sharedStateCb({ dispatch, getState }); sharedStateCb({ dispatch, getState });
} }
clearTimeout(timeout);
return actionResult; return actionResult;
}
timeout = setTimeout(runPreferences, RUN_PREFERENCES_DELAY_MS);
}; };

View file

@ -13,20 +13,17 @@ import mergeClaim from 'util/merge-claim';
type State = { type State = {
createChannelError: ?string, createChannelError: ?string,
createCollectionError: ?string,
channelClaimCounts: { [string]: number }, channelClaimCounts: { [string]: number },
claimsByUri: { [string]: string }, claimsByUri: { [string]: string },
byId: { [string]: Claim }, byId: { [string]: Claim },
pendingById: { [string]: Claim }, // keep pending claims
resolvingUris: Array<string>, resolvingUris: Array<string>,
pendingIds: Array<string>,
reflectingById: { [string]: ReflectingUpdate }, reflectingById: { [string]: ReflectingUpdate },
myClaims: ?Array<string>, myClaims: ?Array<string>,
myChannelClaims: ?Array<string>, myChannelClaims: ?Array<string>,
myCollectionClaims: ?Array<string>,
abandoningById: { [string]: boolean }, abandoningById: { [string]: boolean },
fetchingChannelClaims: { [string]: number }, fetchingChannelClaims: { [string]: number },
fetchingMyChannels: boolean, fetchingMyChannels: boolean,
fetchingMyCollections: boolean,
fetchingClaimSearchByQuery: { [string]: boolean }, fetchingClaimSearchByQuery: { [string]: boolean },
purchaseUriSuccess: boolean, purchaseUriSuccess: boolean,
myPurchases: ?Array<string>, myPurchases: ?Array<string>,
@ -37,7 +34,6 @@ type State = {
claimSearchByQuery: { [string]: Array<string> }, claimSearchByQuery: { [string]: Array<string> },
claimSearchByQueryLastPageReached: { [string]: Array<boolean> }, claimSearchByQueryLastPageReached: { [string]: Array<boolean> },
creatingChannel: boolean, creatingChannel: boolean,
creatingCollection: boolean,
paginatedClaimsByChannel: { paginatedClaimsByChannel: {
[string]: { [string]: {
all: Array<string>, all: Array<string>,
@ -47,9 +43,7 @@ type State = {
}, },
}, },
updateChannelError: ?string, updateChannelError: ?string,
updateCollectionError: ?string,
updatingChannel: boolean, updatingChannel: boolean,
updatingCollection: boolean,
pendingChannelImport: string | boolean, pendingChannelImport: string | boolean,
repostLoading: boolean, repostLoading: boolean,
repostError: ?string, repostError: ?string,
@ -72,7 +66,6 @@ const defaultState = {
fetchingChannelClaims: {}, fetchingChannelClaims: {},
resolvingUris: [], resolvingUris: [],
myChannelClaims: undefined, myChannelClaims: undefined,
myCollectionClaims: [],
myClaims: undefined, myClaims: undefined,
myPurchases: undefined, myPurchases: undefined,
myPurchasesPageNumber: undefined, myPurchasesPageNumber: undefined,
@ -81,22 +74,17 @@ const defaultState = {
fetchingMyPurchases: false, fetchingMyPurchases: false,
fetchingMyPurchasesError: undefined, fetchingMyPurchasesError: undefined,
fetchingMyChannels: false, fetchingMyChannels: false,
fetchingMyCollections: false,
abandoningById: {}, abandoningById: {},
pendingById: {}, pendingIds: [],
reflectingById: {}, reflectingById: {},
claimSearchError: false, claimSearchError: false,
claimSearchByQuery: {}, claimSearchByQuery: {},
claimSearchByQueryLastPageReached: {}, claimSearchByQueryLastPageReached: {},
fetchingClaimSearchByQuery: {}, fetchingClaimSearchByQuery: {},
updateChannelError: '', updateChannelError: '',
updateCollectionError: '',
updatingChannel: false, updatingChannel: false,
creatingChannel: false, creatingChannel: false,
createChannelError: undefined, createChannelError: undefined,
updatingCollection: false,
creatingCollection: false,
createCollectionError: undefined,
pendingChannelImport: false, pendingChannelImport: false,
repostLoading: false, repostLoading: false,
repostError: undefined, repostError: undefined,
@ -112,22 +100,29 @@ const defaultState = {
}; };
function handleClaimAction(state: State, action: any): State { function handleClaimAction(state: State, action: any): State {
const { resolveInfo }: ClaimActionResolveInfo = action.data; const {
resolveInfo,
}: {
[string]: {
stream: ?StreamClaim,
channel: ?ChannelClaim,
claimsInChannel: ?number,
},
} = action.data;
const byUri = Object.assign({}, state.claimsByUri); const byUri = Object.assign({}, state.claimsByUri);
const byId = Object.assign({}, state.byId); const byId = Object.assign({}, state.byId);
const channelClaimCounts = Object.assign({}, state.channelClaimCounts); const channelClaimCounts = Object.assign({}, state.channelClaimCounts);
const pendingById = state.pendingById; const pendingIds = state.pendingIds;
let newResolvingUrls = new Set(state.resolvingUris); let newResolvingUrls = new Set(state.resolvingUris);
let myClaimIds = new Set(state.myClaims); let myClaimIds = new Set(state.myClaims);
Object.entries(resolveInfo).forEach(([url: string, resolveResponse: ResolveResponse]) => { Object.entries(resolveInfo).forEach(([url: string, resolveResponse: ResolveResponse]) => {
// $FlowFixMe // $FlowFixMe
const { claimsInChannel, stream, channel: channelFromResolve, collection } = resolveResponse; const { claimsInChannel, stream, channel } = resolveResponse;
const channel = channelFromResolve || (stream && stream.signing_channel);
if (stream) { if (stream) {
if (pendingById[stream.claim_id]) { if (pendingIds.includes(stream.claim_id)) {
byId[stream.claim_id] = mergeClaim(stream, byId[stream.claim_id]); byId[stream.claim_id] = mergeClaim(stream, byId[stream.claim_id]);
} else { } else {
byId[stream.claim_id] = stream; byId[stream.claim_id] = stream;
@ -157,37 +152,20 @@ function handleClaimAction(state: State, action: any): State {
channelClaimCounts[channel.canonical_url] = claimsInChannel; channelClaimCounts[channel.canonical_url] = claimsInChannel;
} }
if (pendingById[channel.claim_id]) { if (pendingIds.includes(channel.claim_id)) {
byId[channel.claim_id] = mergeClaim(channel, byId[channel.claim_id]); byId[channel.claim_id] = mergeClaim(channel, byId[channel.claim_id]);
} else { } else {
byId[channel.claim_id] = channel; byId[channel.claim_id] = channel;
} }
// Also add the permanent_url here until lighthouse returns canonical_url for search results
byUri[channel.permanent_url] = channel.claim_id; byUri[channel.permanent_url] = channel.claim_id;
byUri[channel.canonical_url] = channel.claim_id; byUri[channel.canonical_url] = channel.claim_id;
newResolvingUrls.delete(channel.canonical_url); newResolvingUrls.delete(channel.canonical_url);
newResolvingUrls.delete(channel.permanent_url); newResolvingUrls.delete(channel.permanent_url);
} }
if (collection) {
if (pendingById[collection.claim_id]) {
byId[collection.claim_id] = mergeClaim(collection, byId[collection.claim_id]);
} else {
byId[collection.claim_id] = collection;
}
byUri[url] = collection.claim_id;
byUri[collection.canonical_url] = collection.claim_id;
byUri[collection.permanent_url] = collection.claim_id;
newResolvingUrls.delete(collection.canonical_url);
newResolvingUrls.delete(collection.permanent_url);
if (collection.is_my_output) {
myClaimIds.add(collection.claim_id);
}
}
newResolvingUrls.delete(url); newResolvingUrls.delete(url);
if (!stream && !channel && !collection && !pendingById[byUri[url]]) { if (!stream && !channel && !pendingIds.includes(byUri[url])) {
byUri[url] = null; byUri[url] = null;
} }
}); });
@ -230,33 +208,34 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED] = (state: State): State =>
}); });
reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any): State => { reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any): State => {
const { result }: { result: ClaimListResponse } = action.data; const { result, resolve }: { result: ClaimListResponse, resolve: boolean } = action.data;
const claims = result.items; const claims = result.items;
const page = result.page; const page = result.page;
const totalItems = result.total_items; const totalItems = result.total_items;
const byId = Object.assign({}, state.byId); const byId = Object.assign({}, state.byId);
const byUri = Object.assign({}, state.claimsByUri); const byUri = Object.assign({}, state.claimsByUri);
const pendingById = Object.assign({}, state.pendingById); const pendingIds = state.pendingIds || [];
let myClaimIds = new Set(state.myClaims); let myClaimIds = new Set(state.myClaims);
let urlsForCurrentPage = []; let urlsForCurrentPage = [];
const pendingIdSet = new Set(pendingIds);
claims.forEach((claim: Claim) => { claims.forEach((claim: Claim) => {
const { permanent_url: permanentUri, claim_id: claimId, canonical_url: canonicalUri } = claim; const { permanent_url: permanentUri, claim_id: claimId } = claim;
if (claim.type && claim.type.match(/claim|update/)) { if (claim.type && claim.type.match(/claim|update/)) {
urlsForCurrentPage.push(permanentUri); urlsForCurrentPage.push(permanentUri);
if (claim.confirmations < 1) { if (claim.confirmations < 1) {
pendingById[claimId] = claim; pendingIdSet.add(claimId);
if (byId[claimId]) { } else if (!resolve && pendingIdSet.has(claimId) && claim.confirmations > 0) {
pendingIdSet.delete(claimId);
}
if (pendingIds.includes(claimId)) {
byId[claimId] = mergeClaim(claim, byId[claimId]); byId[claimId] = mergeClaim(claim, byId[claimId]);
} else { } else {
byId[claimId] = claim; byId[claimId] = claim;
} }
} else {
byId[claimId] = claim;
}
byUri[permanentUri] = claimId; byUri[permanentUri] = claimId;
byUri[canonicalUri] = claimId;
myClaimIds.add(claimId); myClaimIds.add(claimId);
} }
}); });
@ -265,7 +244,7 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any):
isFetchingClaimListMine: false, isFetchingClaimListMine: false,
myClaims: Array.from(myClaimIds), myClaims: Array.from(myClaimIds),
byId, byId,
pendingById, pendingIds: Array.from(pendingIdSet),
claimsByUri: byUri, claimsByUri: byUri,
myClaimsPageResults: urlsForCurrentPage, myClaimsPageResults: urlsForCurrentPage,
myClaimsPageNumber: page, myClaimsPageNumber: page,
@ -278,8 +257,9 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_STARTED] = (state: State): State =>
reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): State => { reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): State => {
const { claims }: { claims: Array<ChannelClaim> } = action.data; const { claims }: { claims: Array<ChannelClaim> } = action.data;
const myClaims = state.myClaims || [];
let myClaimIds = new Set(state.myClaims); let myClaimIds = new Set(state.myClaims);
const pendingById = Object.assign({}, state.pendingById); const pendingIds = state.pendingIds || [];
let myChannelClaims; let myChannelClaims;
const byId = Object.assign({}, state.byId); const byId = Object.assign({}, state.byId);
const byUri = Object.assign({}, state.claimsByUri); const byUri = Object.assign({}, state.claimsByUri);
@ -293,12 +273,7 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): St
claims.forEach(claim => { claims.forEach(claim => {
const { meta } = claim; const { meta } = claim;
const { claims_in_channel: claimsInChannel } = claim.meta; const { claims_in_channel: claimsInChannel } = claim.meta;
const { const { canonical_url: canonicalUrl, permanent_url: permanentUrl, claim_id: claimId } = claim;
canonical_url: canonicalUrl,
permanent_url: permanentUrl,
claim_id: claimId,
confirmations,
} = claim;
byUri[canonicalUrl] = claimId; byUri[canonicalUrl] = claimId;
byUri[permanentUrl] = claimId; byUri[permanentUrl] = claimId;
@ -307,14 +282,7 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): St
// $FlowFixMe // $FlowFixMe
myChannelClaims.add(claimId); myChannelClaims.add(claimId);
if (confirmations < 1) { if (!pendingIds.some(c => c === claimId)) {
pendingById[claimId] = claim;
if (byId[claimId]) {
byId[claimId] = mergeClaim(claim, byId[claimId]);
} else {
byId[claimId] = claim;
}
} else {
byId[claimId] = claim; byId[claimId] = claim;
} }
myClaimIds.add(claimId); myClaimIds.add(claimId);
@ -323,7 +291,6 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): St
return Object.assign({}, state, { return Object.assign({}, state, {
byId, byId,
pendingById,
claimsByUri: byUri, claimsByUri: byUri,
channelClaimCounts, channelClaimCounts,
fetchingMyChannels: false, fetchingMyChannels: false,
@ -338,66 +305,6 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_FAILED] = (state: State, action: any): State
}); });
}; };
reducers[ACTIONS.FETCH_COLLECTION_LIST_STARTED] = (state: State): State => ({
...state,
fetchingMyCollections: true,
});
reducers[ACTIONS.FETCH_COLLECTION_LIST_COMPLETED] = (state: State, action: any): State => {
const { claims }: { claims: Array<CollectionClaim> } = action.data;
const myClaims = state.myClaims || [];
let myClaimIds = new Set(myClaims);
const pendingById = Object.assign({}, state.pendingById);
let myCollectionClaimsSet = new Set([]);
const byId = Object.assign({}, state.byId);
const byUri = Object.assign({}, state.claimsByUri);
if (claims.length) {
myCollectionClaimsSet = new Set(state.myCollectionClaims);
claims.forEach(claim => {
const { meta } = claim;
const {
canonical_url: canonicalUrl,
permanent_url: permanentUrl,
claim_id: claimId,
confirmations,
} = claim;
byUri[canonicalUrl] = claimId;
byUri[permanentUrl] = claimId;
// $FlowFixMe
myCollectionClaimsSet.add(claimId);
// we don't want to overwrite a pending result with a resolve
if (confirmations < 1) {
pendingById[claimId] = claim;
if (byId[claimId]) {
byId[claimId] = mergeClaim(claim, byId[claimId]);
} else {
byId[claimId] = claim;
}
} else {
byId[claimId] = claim;
}
myClaimIds.add(claimId);
});
}
return {
...state,
byId,
pendingById,
claimsByUri: byUri,
fetchingMyCollections: false,
myCollectionClaims: Array.from(myCollectionClaimsSet),
myClaims: myClaimIds ? Array.from(myClaimIds) : null,
};
};
reducers[ACTIONS.FETCH_COLLECTION_LIST_FAILED] = (state: State): State => {
return { ...state, fetchingMyCollections: false };
};
reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED] = (state: State, action: any): State => { reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED] = (state: State, action: any): State => {
const { uri, page } = action.data; const { uri, page } = action.data;
const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims); const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims);
@ -479,8 +386,9 @@ reducers[ACTIONS.ABANDON_CLAIM_STARTED] = (state: State, action: any): State =>
reducers[ACTIONS.UPDATE_PENDING_CLAIMS] = (state: State, action: any): State => { reducers[ACTIONS.UPDATE_PENDING_CLAIMS] = (state: State, action: any): State => {
const { claims: pendingClaims }: { claims: Array<Claim> } = action.data; const { claims: pendingClaims }: { claims: Array<Claim> } = action.data;
const byId = Object.assign({}, state.byId); const byId = Object.assign({}, state.byId);
const pendingById = Object.assign({}, state.pendingById);
const byUri = Object.assign({}, state.claimsByUri); const byUri = Object.assign({}, state.claimsByUri);
const pendingIds = state.pendingIds;
const pendingIdSet = new Set(pendingIds);
let myClaimIds = new Set(state.myClaims); let myClaimIds = new Set(state.myClaims);
const myChannelClaims = new Set(state.myChannelClaims); const myChannelClaims = new Set(state.myChannelClaims);
@ -488,7 +396,7 @@ reducers[ACTIONS.UPDATE_PENDING_CLAIMS] = (state: State, action: any): State =>
pendingClaims.forEach((claim: Claim) => { pendingClaims.forEach((claim: Claim) => {
let newClaim; let newClaim;
const { permanent_url: uri, claim_id: claimId, type, value_type: valueType } = claim; const { permanent_url: uri, claim_id: claimId, type, value_type: valueType } = claim;
pendingById[claimId] = claim; // make sure we don't need to merge? pendingIdSet.add(claimId);
const oldClaim = byId[claimId]; const oldClaim = byId[claimId];
if (oldClaim && oldClaim.canonical_url) { if (oldClaim && oldClaim.canonical_url) {
newClaim = mergeClaim(oldClaim, claim); newClaim = mergeClaim(oldClaim, claim);
@ -508,22 +416,21 @@ reducers[ACTIONS.UPDATE_PENDING_CLAIMS] = (state: State, action: any): State =>
return Object.assign({}, state, { return Object.assign({}, state, {
myClaims: Array.from(myClaimIds), myClaims: Array.from(myClaimIds),
byId, byId,
pendingById,
myChannelClaims: Array.from(myChannelClaims), myChannelClaims: Array.from(myChannelClaims),
claimsByUri: byUri, claimsByUri: byUri,
pendingIds: Array.from(pendingIdSet),
}); });
}; };
reducers[ACTIONS.UPDATE_CONFIRMED_CLAIMS] = (state: State, action: any): State => { reducers[ACTIONS.UPDATE_CONFIRMED_CLAIMS] = (state: State, action: any): State => {
const { const { claims: confirmedClaims }: { claims: Array<Claim> } = action.data;
claims: confirmedClaims,
pending: pendingClaims,
}: { claims: Array<Claim>, pending: { [string]: Claim } } = action.data;
const byId = Object.assign({}, state.byId); const byId = Object.assign({}, state.byId);
const byUri = Object.assign({}, state.claimsByUri); const byUri = Object.assign({}, state.claimsByUri);
// const pendingIds = state.pendingIds;
const pendingIdSet = new Set(pendingIds);
confirmedClaims.forEach((claim: GenericClaim) => { confirmedClaims.forEach((claim: GenericClaim) => {
const { claim_id: claimId, type } = claim; const { permanent_url: permanentUri, claim_id: claimId, type } = claim;
let newClaim = claim; let newClaim = claim;
const oldClaim = byId[claimId]; const oldClaim = byId[claimId];
if (oldClaim && oldClaim.canonical_url) { if (oldClaim && oldClaim.canonical_url) {
@ -531,10 +438,11 @@ reducers[ACTIONS.UPDATE_CONFIRMED_CLAIMS] = (state: State, action: any): State =
} }
if (type && type.match(/claim|update|channel/)) { if (type && type.match(/claim|update|channel/)) {
byId[claimId] = newClaim; byId[claimId] = newClaim;
pendingIdSet.delete(claimId);
} }
}); });
return Object.assign({}, state, { return Object.assign({}, state, {
pendingById: pendingClaims, pendingIds: Array.from(pendingIdSet),
byId, byId,
claimsByUri: byUri, claimsByUri: byUri,
}); });
@ -546,7 +454,6 @@ reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = (state: State, action: any): State =
const newMyClaims = state.myClaims ? state.myClaims.slice() : []; const newMyClaims = state.myClaims ? state.myClaims.slice() : [];
const newMyChannelClaims = state.myChannelClaims ? state.myChannelClaims.slice() : []; const newMyChannelClaims = state.myChannelClaims ? state.myChannelClaims.slice() : [];
const claimsByUri = Object.assign({}, state.claimsByUri); const claimsByUri = Object.assign({}, state.claimsByUri);
const newMyCollectionClaims = state.myCollectionClaims ? state.myCollectionClaims.slice() : [];
Object.keys(claimsByUri).forEach(uri => { Object.keys(claimsByUri).forEach(uri => {
if (claimsByUri[uri] === claimId) { if (claimsByUri[uri] === claimId) {
@ -555,14 +462,12 @@ reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = (state: State, action: any): State =
}); });
const myClaims = newMyClaims.filter(i => i !== claimId); const myClaims = newMyClaims.filter(i => i !== claimId);
const myChannelClaims = newMyChannelClaims.filter(i => i !== claimId); const myChannelClaims = newMyChannelClaims.filter(i => i !== claimId);
const myCollectionClaims = newMyCollectionClaims.filter(i => i !== claimId);
delete byId[claimId]; delete byId[claimId];
return Object.assign({}, state, { return Object.assign({}, state, {
myClaims, myClaims,
myChannelClaims, myChannelClaims,
myCollectionClaims,
byId, byId,
claimsByUri, claimsByUri,
}); });
@ -614,61 +519,6 @@ reducers[ACTIONS.UPDATE_CHANNEL_FAILED] = (state: State, action: any): State =>
}); });
}; };
reducers[ACTIONS.CLEAR_COLLECTION_ERRORS] = (state: State): State => ({
...state,
createCollectionError: null,
updateCollectionError: null,
});
reducers[ACTIONS.COLLECTION_PUBLISH_STARTED] = (state: State): State => ({
...state,
creatingCollection: true,
createCollectionError: null,
});
reducers[ACTIONS.COLLECTION_PUBLISH_COMPLETED] = (state: State, action: any): State => {
const myCollections = state.myCollectionClaims || [];
const myClaims = state.myClaims || [];
const { claimId } = action.data;
let myClaimIds = new Set(myClaims);
let myCollectionClaimsSet = new Set(myCollections);
myClaimIds.add(claimId);
myCollectionClaimsSet.add(claimId);
return Object.assign({}, state, {
creatingCollection: false,
myClaims: Array.from(myClaimIds),
myCollectionClaims: Array.from(myCollectionClaimsSet),
});
};
reducers[ACTIONS.COLLECTION_PUBLISH_FAILED] = (state: State, action: any): State => {
return Object.assign({}, state, {
creatingCollection: false,
createCollectionError: action.data.error,
});
};
reducers[ACTIONS.COLLECTION_PUBLISH_UPDATE_STARTED] = (state: State, action: any): State => {
return Object.assign({}, state, {
updateCollectionError: '',
updatingCollection: true,
});
};
reducers[ACTIONS.COLLECTION_PUBLISH_UPDATE_COMPLETED] = (state: State, action: any): State => {
return Object.assign({}, state, {
updateCollectionError: '',
updatingCollection: false,
});
};
reducers[ACTIONS.COLLECTION_PUBLISH_UPDATE_FAILED] = (state: State, action: any): State => {
return Object.assign({}, state, {
updateCollectionError: action.data.error,
updatingCollection: false,
});
};
reducers[ACTIONS.IMPORT_CHANNEL_STARTED] = (state: State): State => reducers[ACTIONS.IMPORT_CHANNEL_STARTED] = (state: State): State =>
Object.assign({}, state, { pendingChannelImports: true }); Object.assign({}, state, { pendingChannelImports: true });
@ -720,23 +570,13 @@ reducers[ACTIONS.CLAIM_SEARCH_FAILED] = (state: State, action: any): State => {
const { query } = action.data; const { query } = action.data;
const claimSearchByQuery = Object.assign({}, state.claimSearchByQuery); const claimSearchByQuery = Object.assign({}, state.claimSearchByQuery);
const fetchingClaimSearchByQuery = Object.assign({}, state.fetchingClaimSearchByQuery); const fetchingClaimSearchByQuery = Object.assign({}, state.fetchingClaimSearchByQuery);
const claimSearchByQueryLastPageReached = Object.assign(
{},
state.claimSearchByQueryLastPageReached
);
delete fetchingClaimSearchByQuery[query]; delete fetchingClaimSearchByQuery[query];
if (claimSearchByQuery[query] && claimSearchByQuery[query].length !== 0) {
claimSearchByQueryLastPageReached[query] = true;
} else {
claimSearchByQuery[query] = null; claimSearchByQuery[query] = null;
}
return Object.assign({}, state, { return Object.assign({}, state, {
fetchingClaimSearchByQuery, fetchingClaimSearchByQuery,
claimSearchByQuery, claimSearchByQuery,
claimSearchByQueryLastPageReached,
}); });
}; };

View file

@ -1,239 +0,0 @@
// @flow
import { handleActions } from 'util/redux-utils';
import * as ACTIONS from 'constants/action_types';
import * as COLS from 'constants/collections';
const getTimestamp = () => {
return Math.floor(Date.now() / 1000);
};
const defaultState: CollectionState = {
builtin: {
watchlater: {
items: [],
id: COLS.WATCH_LATER_ID,
name: 'Watch Later',
updatedAt: getTimestamp(),
type: COLS.COL_TYPE_PLAYLIST,
},
favorites: {
items: [],
id: COLS.FAVORITES_ID,
name: 'Favorites',
type: COLS.COL_TYPE_PLAYLIST,
updatedAt: getTimestamp(),
},
},
resolved: {},
unpublished: {}, // sync
edited: {},
pending: {},
saved: [],
isResolvingCollectionById: {},
error: null,
};
const collectionsReducer = handleActions(
{
[ACTIONS.COLLECTION_NEW]: (state, action) => {
const { entry: params } = action.data; // { id:, items: Array<string>}
// entry
const newListTemplate = {
id: params.id,
name: params.name,
items: [],
updatedAt: getTimestamp(),
type: params.type,
};
const newList = Object.assign({}, newListTemplate, { ...params });
const { unpublished: lists } = state;
const newLists = Object.assign({}, lists, { [params.id]: newList });
return {
...state,
unpublished: newLists,
};
},
[ACTIONS.COLLECTION_DELETE]: (state, action) => {
const { id, collectionKey } = action.data;
const { edited: editList, unpublished: unpublishedList, pending: pendingList } = state;
const newEditList = Object.assign({}, editList);
const newUnpublishedList = Object.assign({}, unpublishedList);
const newPendingList = Object.assign({}, pendingList);
if (collectionKey && state[collectionKey] && state[collectionKey][id]) {
const newList = Object.assign({}, state[collectionKey]);
delete newList[id];
return {
...state,
[collectionKey]: newList,
};
} else {
if (newEditList[id]) {
delete newEditList[id];
} else if (newUnpublishedList[id]) {
delete newUnpublishedList[id];
} else if (newPendingList[id]) {
delete newPendingList[id];
}
}
return {
...state,
edited: newEditList,
unpublished: newUnpublishedList,
pending: newPendingList,
};
},
[ACTIONS.COLLECTION_PENDING]: (state, action) => {
const { localId, claimId } = action.data;
const {
resolved: resolvedList,
edited: editList,
unpublished: unpublishedList,
pending: pendingList,
} = state;
const newEditList = Object.assign({}, editList);
const newResolvedList = Object.assign({}, resolvedList);
const newUnpublishedList = Object.assign({}, unpublishedList);
const newPendingList = Object.assign({}, pendingList);
if (localId) {
// new publish
newPendingList[claimId] = Object.assign({}, newUnpublishedList[localId] || {});
delete newUnpublishedList[localId];
} else {
// edit update
newPendingList[claimId] = Object.assign(
{},
newEditList[claimId] || newResolvedList[claimId]
);
delete newEditList[claimId];
}
return {
...state,
edited: newEditList,
unpublished: newUnpublishedList,
pending: newPendingList,
};
},
[ACTIONS.COLLECTION_EDIT]: (state, action) => {
const { id, collectionKey, collection } = action.data;
if (COLS.BUILTIN_LISTS.includes(id)) {
const { builtin: lists } = state;
return {
...state,
[collectionKey]: { ...lists, [id]: collection },
};
}
if (collectionKey === 'edited') {
const { edited: lists } = state;
return {
...state,
edited: { ...lists, [id]: collection },
};
}
const { unpublished: lists } = state;
return {
...state,
unpublished: { ...lists, [id]: collection },
};
},
[ACTIONS.COLLECTION_ERROR]: (state, action) => {
return Object.assign({}, state, {
error: action.data.message,
});
},
[ACTIONS.COLLECTION_ITEMS_RESOLVE_STARTED]: (state, action) => {
const { ids } = action.data;
const { isResolvingCollectionById } = state;
const newResolving = Object.assign({}, isResolvingCollectionById);
ids.forEach(id => {
newResolving[id] = true;
});
return Object.assign({}, state, {
...state,
error: '',
isResolvingCollectionById: newResolving,
});
},
[ACTIONS.USER_STATE_POPULATE]: (state, action) => {
const {
builtinCollections,
savedCollections,
unpublishedCollections,
editedCollections,
} = action.data;
return {
...state,
edited: editedCollections || state.edited,
unpublished: unpublishedCollections || state.unpublished,
builtin: builtinCollections || state.builtin,
saved: savedCollections || state.saved,
};
},
[ACTIONS.COLLECTION_ITEMS_RESOLVE_COMPLETED]: (state, action) => {
const { resolvedCollections, failedCollectionIds } = action.data;
const { pending, edited, isResolvingCollectionById, resolved } = state;
const newPending = Object.assign({}, pending);
const newEdited = Object.assign({}, edited);
const newResolved = Object.assign({}, resolved, resolvedCollections);
const resolvedIds = Object.keys(resolvedCollections);
const newResolving = Object.assign({}, isResolvingCollectionById);
if (resolvedCollections && Object.keys(resolvedCollections).length) {
resolvedIds.forEach(resolvedId => {
if (newEdited[resolvedId]) {
if (newEdited[resolvedId]['updatedAt'] < resolvedCollections[resolvedId]['updatedAt']) {
delete newEdited[resolvedId];
}
}
delete newResolving[resolvedId];
if (newPending[resolvedId]) {
delete newPending[resolvedId];
}
});
}
if (failedCollectionIds && Object.keys(failedCollectionIds).length) {
failedCollectionIds.forEach(failedId => {
delete newResolving[failedId];
});
}
return Object.assign({}, state, {
...state,
pending: newPending,
resolved: newResolved,
edited: newEdited,
isResolvingCollectionById: newResolving,
});
},
[ACTIONS.COLLECTION_ITEMS_RESOLVE_FAILED]: (state, action) => {
const { ids } = action.data;
const { isResolvingCollectionById } = state;
const newResolving = Object.assign({}, isResolvingCollectionById);
ids.forEach(id => {
delete newResolving[id];
});
return Object.assign({}, state, {
...state,
isResolvingCollectionById: newResolving,
error: action.data.message,
});
},
},
defaultState
);
export { collectionsReducer };

View file

@ -9,7 +9,6 @@ type PublishState = {
editingURI: ?string, editingURI: ?string,
fileText: ?string, fileText: ?string,
filePath: ?string, filePath: ?string,
remoteFileUrl: ?string,
contentIsFree: boolean, contentIsFree: boolean,
fileDur: number, fileDur: number,
fileSize: number, fileSize: number,
@ -22,11 +21,8 @@ type PublishState = {
thumbnail_url: string, thumbnail_url: string,
thumbnailPath: string, thumbnailPath: string,
uploadThumbnailStatus: string, uploadThumbnailStatus: string,
thumbnailError: ?boolean,
description: string, description: string,
language: string, language: string,
releaseTime: ?number,
releaseTimeEdited: ?number,
channel: string, channel: string,
channelId: ?string, channelId: ?string,
name: string, name: string,
@ -47,7 +43,6 @@ const defaultState: PublishState = {
fileDur: 0, fileDur: 0,
fileSize: 0, fileSize: 0,
fileVid: false, fileVid: false,
remoteFileUrl: undefined,
contentIsFree: true, contentIsFree: true,
fee: { fee: {
amount: 1, amount: 1,
@ -57,17 +52,14 @@ const defaultState: PublishState = {
thumbnail_url: '', thumbnail_url: '',
thumbnailPath: '', thumbnailPath: '',
uploadThumbnailStatus: THUMBNAIL_STATUSES.API_DOWN, uploadThumbnailStatus: THUMBNAIL_STATUSES.API_DOWN,
thumbnailError: undefined,
description: '', description: '',
language: '', language: '',
releaseTime: undefined,
releaseTimeEdited: undefined,
nsfw: false, nsfw: false,
channel: CHANNEL_ANONYMOUS, channel: CHANNEL_ANONYMOUS,
channelId: '', channelId: '',
name: '', name: '',
nameError: undefined, nameError: undefined,
bid: 0.01, bid: 0.1,
bidError: undefined, bidError: undefined,
licenseType: 'None', licenseType: 'None',
otherLicenseDescription: 'All rights reserved', otherLicenseDescription: 'All rights reserved',
@ -91,11 +83,9 @@ export const publishReducer = handleActions(
}, },
[ACTIONS.CLEAR_PUBLISH]: (state: PublishState): PublishState => ({ [ACTIONS.CLEAR_PUBLISH]: (state: PublishState): PublishState => ({
...defaultState, ...defaultState,
uri: undefined,
channel: state.channel, channel: state.channel,
bid: state.bid, bid: state.bid,
optimize: state.optimize, optimize: state.optimize,
language: state.language,
}), }),
[ACTIONS.PUBLISH_START]: (state: PublishState): PublishState => ({ [ACTIONS.PUBLISH_START]: (state: PublishState): PublishState => ({
...state, ...state,

View file

@ -0,0 +1,86 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import { handleActions } from 'util/redux-utils';
import { DEFAULT_KNOWN_TAGS, DEFAULT_FOLLOWED_TAGS } from 'constants/tags';
function getDefaultKnownTags() {
return DEFAULT_FOLLOWED_TAGS.concat(DEFAULT_KNOWN_TAGS).reduce(
(tagsMap, tag) => ({
...tagsMap,
[tag]: { name: tag },
}),
{}
);
}
const defaultState: TagState = {
followedTags: [],
knownTags: getDefaultKnownTags(),
};
export const tagsReducer = handleActions(
{
[ACTIONS.TOGGLE_TAG_FOLLOW]: (state: TagState, action: TagAction): TagState => {
const { followedTags } = state;
const { name } = action.data;
let newFollowedTags = followedTags.slice();
if (newFollowedTags.includes(name)) {
newFollowedTags = newFollowedTags.filter(tag => tag !== name);
} else {
newFollowedTags.push(name);
}
return {
...state,
followedTags: newFollowedTags,
};
},
[ACTIONS.TAG_ADD]: (state: TagState, action: TagAction) => {
const { knownTags } = state;
const { name } = action.data;
let newKnownTags = { ...knownTags };
newKnownTags[name] = { name };
return {
...state,
knownTags: newKnownTags,
};
},
[ACTIONS.TAG_DELETE]: (state: TagState, action: TagAction) => {
const { knownTags, followedTags } = state;
const { name } = action.data;
let newKnownTags = { ...knownTags };
delete newKnownTags[name];
const newFollowedTags = followedTags.filter(tag => tag !== name);
return {
...state,
knownTags: newKnownTags,
followedTags: newFollowedTags,
};
},
[ACTIONS.USER_STATE_POPULATE]: (
state: TagState,
action: { data: { tags: ?Array<string> } }
) => {
const { tags } = action.data;
if (Array.isArray(tags)) {
return {
...state,
followedTags: tags,
};
}
return {
...state,
};
},
},
defaultState
);

View file

@ -45,17 +45,10 @@ type WalletState = {
walletLockResult: ?boolean, walletLockResult: ?boolean,
walletReconnecting: boolean, walletReconnecting: boolean,
txoFetchParams: {}, txoFetchParams: {},
utxoCounts: {},
txoPage: any, txoPage: any,
fetchId: string,
fetchingTxos: boolean, fetchingTxos: boolean,
fetchingTxosError?: string, fetchingTxosError?: string,
consolidatingUtxos: boolean,
pendingConsolidateTxid?: string,
massClaimingTips: boolean,
pendingMassClaimTxid?: string,
pendingSupportTransactions: {}, // { claimId: {txid: 123, amount 12.3}, } pendingSupportTransactions: {}, // { claimId: {txid: 123, amount 12.3}, }
pendingTxos: Array<string>,
abandonClaimSupportError?: string, abandonClaimSupportError?: string,
}; };
@ -92,20 +85,10 @@ const defaultState = {
transactionListFilter: 'all', transactionListFilter: 'all',
walletReconnecting: false, walletReconnecting: false,
txoFetchParams: {}, txoFetchParams: {},
utxoCounts: {},
fetchingUtxoCounts: false,
fetchingUtxoError: undefined,
consolidatingUtxos: false,
pendingConsolidateTxid: null,
massClaimingTips: false,
pendingMassClaimTxid: null,
txoPage: {}, txoPage: {},
fetchId: '',
fetchingTxos: false, fetchingTxos: false,
fetchingTxosError: undefined, fetchingTxosError: undefined,
pendingSupportTransactions: {}, pendingSupportTransactions: {},
pendingTxos: [],
abandonClaimSupportError: undefined, abandonClaimSupportError: undefined,
}; };
@ -131,26 +114,18 @@ export const walletReducer = handleActions(
}; };
}, },
[ACTIONS.FETCH_TXO_PAGE_STARTED]: (state: WalletState, action) => { [ACTIONS.FETCH_TXO_PAGE_STARTED]: (state: WalletState) => {
return { return {
...state, ...state,
fetchId: action.data,
fetchingTxos: true, fetchingTxos: true,
fetchingTxosError: undefined, fetchingTxosError: undefined,
}; };
}, },
[ACTIONS.FETCH_TXO_PAGE_COMPLETED]: (state: WalletState, action) => { [ACTIONS.FETCH_TXO_PAGE_COMPLETED]: (state: WalletState, action) => {
if (state.fetchId !== action.data.fetchId) {
// Leave 'state' and 'fetchingTxos' alone. The latter would ensure
// the spiner would continue spinning for the latest transaction.
return { ...state };
}
return { return {
...state, ...state,
txoPage: action.data.result, txoPage: action.data,
fetchId: '',
fetchingTxos: false, fetchingTxos: false,
}; };
}, },
@ -159,104 +134,10 @@ export const walletReducer = handleActions(
return { return {
...state, ...state,
txoPage: {}, txoPage: {},
fetchId: '',
fetchingTxos: false, fetchingTxos: false,
fetchingTxosError: action.data, fetchingTxosError: action.data,
}; };
}, },
[ACTIONS.FETCH_UTXO_COUNT_STARTED]: (state: WalletState) => {
return {
...state,
fetchingUtxoCounts: true,
fetchingUtxoError: undefined,
};
},
[ACTIONS.FETCH_UTXO_COUNT_COMPLETED]: (state: WalletState, action) => {
return {
...state,
utxoCounts: action.data,
fetchingUtxoCounts: false,
};
},
[ACTIONS.FETCH_UTXO_COUNT_FAILED]: (state: WalletState, action) => {
return {
...state,
utxoCounts: {},
fetchingUtxoCounts: false,
fetchingUtxoError: action.data,
};
},
[ACTIONS.DO_UTXO_CONSOLIDATE_STARTED]: (state: WalletState) => {
return {
...state,
consolidatingUtxos: true,
};
},
[ACTIONS.DO_UTXO_CONSOLIDATE_COMPLETED]: (state: WalletState, action) => {
const { txid } = action.data;
return {
...state,
consolidatingUtxos: false,
pendingConsolidateTxid: txid,
};
},
[ACTIONS.DO_UTXO_CONSOLIDATE_FAILED]: (state: WalletState, action) => {
return {
...state,
consolidatingUtxos: false,
};
},
[ACTIONS.TIP_CLAIM_MASS_STARTED]: (state: WalletState) => {
return {
...state,
massClaimingTips: true,
};
},
[ACTIONS.TIP_CLAIM_MASS_COMPLETED]: (state: WalletState, action) => {
const { txid } = action.data;
return {
...state,
massClaimingTips: false,
pendingMassClaimTxid: txid,
};
},
[ACTIONS.TIP_CLAIM_MASS_FAILED]: (state: WalletState, action) => {
return {
...state,
massClaimingTips: false,
};
},
[ACTIONS.PENDING_CONSOLIDATED_TXOS_UPDATED]: (state: WalletState, action) => {
const { pendingTxos, pendingMassClaimTxid, pendingConsolidateTxid } = state;
const { txids, remove } = action.data;
if (remove) {
const newTxos = pendingTxos.filter(txo => !txids.includes(txo));
const newPendingMassClaimTxid = txids.includes(pendingMassClaimTxid)
? undefined
: pendingMassClaimTxid;
const newPendingConsolidateTxid = txids.includes(pendingConsolidateTxid)
? undefined
: pendingConsolidateTxid;
return {
...state,
pendingTxos: newTxos,
pendingMassClaimTxid: newPendingMassClaimTxid,
pendingConsolidateTxid: newPendingConsolidateTxid,
};
} else {
const newPendingSet = new Set([...pendingTxos, ...txids]);
return { ...state, pendingTxos: Array.from(newPendingSet) };
}
},
[ACTIONS.UPDATE_TXO_FETCH_PARAMS]: (state: WalletState, action) => { [ACTIONS.UPDATE_TXO_FETCH_PARAMS]: (state: WalletState, action) => {
return { return {
@ -305,7 +186,7 @@ export const walletReducer = handleActions(
return { return {
...state, ...state,
supports: byOutpoint, supports: byOutpoint,
abandoningSupportsByOutpoint: currentlyAbandoning, abandoningSupportsById: currentlyAbandoning,
}; };
}, },
@ -324,12 +205,7 @@ export const walletReducer = handleActions(
}, },
[ACTIONS.ABANDON_CLAIM_SUPPORT_COMPLETED]: (state: WalletState, action: any): WalletState => { [ACTIONS.ABANDON_CLAIM_SUPPORT_COMPLETED]: (state: WalletState, action: any): WalletState => {
const { const { claimId, type, txid, effective }: { claimId: string, type: string, txid: string, effective: string } = action.data;
claimId,
type,
txid,
effective,
}: { claimId: string, type: string, txid: string, effective: string } = action.data;
const pendingtxs = Object.assign({}, state.pendingSupportTransactions); const pendingtxs = Object.assign({}, state.pendingSupportTransactions);
pendingtxs[claimId] = {txid, type, effective}; pendingtxs[claimId] = {txid, type, effective};
@ -349,6 +225,7 @@ export const walletReducer = handleActions(
}, },
[ACTIONS.PENDING_SUPPORTS_UPDATED]: (state: WalletState, action: any): WalletState => { [ACTIONS.PENDING_SUPPORTS_UPDATED]: (state: WalletState, action: any): WalletState => {
return { return {
...state, ...state,
pendingSupportTransactions: action.data, pendingSupportTransactions: action.data,

View file

@ -1,30 +1,17 @@
// @flow // @flow
import { normalizeURI, parseURI } from 'lbryURI'; import { normalizeURI, buildURI, parseURI } from 'lbryURI';
import { selectSupportsByOutpoint } from 'redux/selectors/wallet'; import { selectSupportsByOutpoint } from 'redux/selectors/wallet';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { isClaimNsfw, filterClaims } from 'util/claim'; import { isClaimNsfw, filterClaims } from 'util/claim';
import * as CLAIM from 'constants/claim'; import { PAGE_SIZE } from 'constants/claim';
const selectState = state => state.claims || {}; const selectState = state => state.claims || {};
export const selectById = createSelector( export const selectClaimsById = createSelector(
selectState, selectState,
state => state.byId || {} state => state.byId || {}
); );
export const selectPendingClaimsById = createSelector(
selectState,
state => state.pendingById || {}
);
export const selectClaimsById = createSelector(
selectById,
selectPendingClaimsById,
(byId, pendingById) => {
return Object.assign(byId, pendingById); // do I need merged to keep metadata?
}
);
export const selectClaimIdsByUri = createSelector( export const selectClaimIdsByUri = createSelector(
selectState, selectState,
state => state.claimsByUri || {} state => state.claimsByUri || {}
@ -85,53 +72,28 @@ export const selectAllClaimsByChannel = createSelector(
export const selectPendingIds = createSelector( export const selectPendingIds = createSelector(
selectState, selectState,
state => Object.keys(state.pendingById) || [] state => state.pendingIds || []
);
export const selectPendingClaims = createSelector(
selectPendingClaimsById,
pendingById => Object.values(pendingById)
); );
export const makeSelectClaimIsPending = (uri: string) => export const makeSelectClaimIsPending = (uri: string) =>
createSelector( createSelector(
selectClaimIdsByUri, selectClaimIdsByUri,
selectPendingClaimsById, selectPendingIds,
(idsByUri, pendingById) => { (idsByUri, pendingIds) => {
const claimId = idsByUri[normalizeURI(uri)]; const claimId = idsByUri[normalizeURI(uri)];
if (claimId) { if (claimId) {
return Boolean(pendingById[claimId]); return pendingIds.some(i => i === claimId);
} }
return false; return false;
} }
); );
export const makeSelectClaimIdIsPending = (claimId: string) =>
createSelector(
selectPendingClaimsById,
pendingById => {
return Boolean(pendingById[claimId]);
}
);
export const makeSelectClaimIdForUri = (uri: string) =>
createSelector(
selectClaimIdsByUri,
claimIds => claimIds[uri]
);
export const selectReflectingById = createSelector( export const selectReflectingById = createSelector(
selectState, selectState,
state => state.reflectingById state => state.reflectingById
); );
export const makeSelectClaimForClaimId = (claimId: string) =>
createSelector(
selectClaimsById,
byId => byId[claimId]
);
export const makeSelectClaimForUri = (uri: string, returnRepost: boolean = true) => export const makeSelectClaimForUri = (uri: string, returnRepost: boolean = true) =>
createSelector( createSelector(
selectClaimIdsByUri, selectClaimIdsByUri,
@ -157,17 +119,14 @@ export const makeSelectClaimForUri = (uri: string, returnRepost: boolean = true)
return undefined; return undefined;
} }
const repostedClaim = claim && claim.reposted_claim; const repostedClaim = claim.reposted_claim;
if (repostedClaim && returnRepost) { if (repostedClaim && returnRepost) {
const channelUrl = const channelUrl = claim.signing_channel && claim.signing_channel.canonical_url;
claim.signing_channel &&
(claim.signing_channel.canonical_url || claim.signing_channel.permanent_url);
return { return {
...repostedClaim, ...repostedClaim,
repost_url: normalizeURI(uri), repost_url: uri,
repost_channel_url: channelUrl, repost_channel_url: channelUrl,
repost_bid_amount: claim && claim.meta && claim.meta.effective_amount,
}; };
} else { } else {
return claim; return claim;
@ -201,8 +160,7 @@ export const selectAbandoningIds = createSelector(
state => Object.keys(state.abandoningById || {}) state => Object.keys(state.abandoningById || {})
); );
export const makeSelectAbandoningClaimById = (claimId: string) => export const makeSelectAbandoningClaimById = (claimId: string) => createSelector(
createSelector(
selectAbandoningIds, selectAbandoningIds,
ids => ids.includes(claimId) ids => ids.includes(claimId)
); );
@ -295,8 +253,8 @@ export const makeSelectMyPurchasesForPage = (query: ?string, page: number = 1) =
const fileInfos = myPurchases.map(uri => claimsByUri[uri]); const fileInfos = myPurchases.map(uri => claimsByUri[uri]);
const matchingFileInfos = filterClaims(fileInfos, query); const matchingFileInfos = filterClaims(fileInfos, query);
const start = (Number(page) - 1) * Number(CLAIM.PAGE_SIZE); const start = (Number(page) - 1) * Number(PAGE_SIZE);
const end = Number(page) * Number(CLAIM.PAGE_SIZE); const end = Number(page) * Number(PAGE_SIZE);
return matchingFileInfos && matchingFileInfos.length return matchingFileInfos && matchingFileInfos.length
? matchingFileInfos ? matchingFileInfos
.slice(start, end) .slice(start, end)
@ -338,7 +296,6 @@ export const makeSelectClaimsInChannelForPage = (uri: string, page?: number) =>
} }
); );
// THIS IS LEFT OVER FROM ONE TAB CHANNEL_CONTENT
export const makeSelectTotalClaimsInChannelSearch = (uri: string) => export const makeSelectTotalClaimsInChannelSearch = (uri: string) =>
createSelector( createSelector(
selectClaimsById, selectClaimsById,
@ -349,7 +306,6 @@ export const makeSelectTotalClaimsInChannelSearch = (uri: string) =>
} }
); );
// THIS IS LEFT OVER FROM ONE_TAB CHANNEL CONTENT
export const makeSelectTotalPagesInChannelSearch = (uri: string) => export const makeSelectTotalPagesInChannelSearch = (uri: string) =>
createSelector( createSelector(
selectClaimsById, selectClaimsById,
@ -360,6 +316,21 @@ export const makeSelectTotalPagesInChannelSearch = (uri: string) =>
} }
); );
export const makeSelectClaimsInChannelForCurrentPageState = (uri: string) =>
createSelector(
selectClaimsById,
selectAllClaimsByChannel,
selectCurrentChannelPage,
(byId, allClaims, page) => {
const byChannel = allClaims[uri] || {};
const claimIds = byChannel[page || 1];
if (!claimIds) return claimIds;
return claimIds.map(claimId => byId[claimId]);
}
);
export const makeSelectMetadataForUri = (uri: string) => export const makeSelectMetadataForUri = (uri: string) =>
createSelector( createSelector(
makeSelectClaimForUri(uri), makeSelectClaimForUri(uri),
@ -411,19 +382,6 @@ export const makeSelectAmountForUri = (uri: string) =>
} }
); );
export const makeSelectEffectiveAmountForUri = (uri: string) =>
createSelector(
makeSelectClaimForUri(uri, false),
claim => {
return (
claim &&
claim.meta &&
typeof claim.meta.effective_amount === 'string' &&
Number(claim.meta.effective_amount)
);
}
);
export const makeSelectContentTypeForUri = (uri: string) => export const makeSelectContentTypeForUri = (uri: string) =>
createSelector( createSelector(
makeSelectClaimForUri(uri), makeSelectClaimForUri(uri),
@ -500,9 +458,7 @@ export const selectMyClaims = createSelector(
export const selectMyClaimsWithoutChannels = createSelector( export const selectMyClaimsWithoutChannels = createSelector(
selectMyClaims, selectMyClaims,
myClaims => myClaims =>
myClaims myClaims.filter(claim => !claim.name.match(/^@/)).sort((a, b) => a.timestamp - b.timestamp)
.filter(claim => claim && !claim.name.match(/^@/))
.sort((a, b) => a.timestamp - b.timestamp)
); );
export const selectMyClaimUrisWithoutChannels = createSelector( export const selectMyClaimUrisWithoutChannels = createSelector(
@ -546,11 +502,6 @@ export const selectFetchingMyChannels = createSelector(
state => state.fetchingMyChannels state => state.fetchingMyChannels
); );
export const selectFetchingMyCollections = createSelector(
selectState,
state => state.fetchingMyCollections
);
export const selectMyChannelClaims = createSelector( export const selectMyChannelClaims = createSelector(
selectState, selectState,
selectClaimsById, selectClaimsById,
@ -577,11 +528,6 @@ export const selectMyChannelUrls = createSelector(
claims => (claims ? claims.map(claim => claim.canonical_url || claim.permanent_url) : undefined) claims => (claims ? claims.map(claim => claim.canonical_url || claim.permanent_url) : undefined)
); );
export const selectMyCollectionIds = createSelector(
selectState,
state => state.myCollectionClaims
);
export const selectResolvingUris = createSelector( export const selectResolvingUris = createSelector(
selectState, selectState,
state => state.resolvingUris || [] state => state.resolvingUris || []
@ -608,35 +554,16 @@ export const selectChannelClaimCounts = createSelector(
state => state.channelClaimCounts || {} state => state.channelClaimCounts || {}
); );
export const makeSelectPendingClaimForUri = (uri: string) =>
createSelector(
selectPendingClaimsById,
pendingById => {
let uriStreamName;
let uriChannelName;
try {
({ streamName: uriStreamName, channelName: uriChannelName } = parseURI(uri));
} catch (e) {
return null;
}
const pendingClaims = (Object.values(pendingById): any);
const matchingClaim = pendingClaims.find((claim: GenericClaim) => {
return claim.normalized_name === uriChannelName || claim.normalized_name === uriStreamName;
});
return matchingClaim || null;
}
);
export const makeSelectTotalItemsForChannel = (uri: string) => export const makeSelectTotalItemsForChannel = (uri: string) =>
createSelector( createSelector(
selectChannelClaimCounts, selectChannelClaimCounts,
byUri => byUri && byUri[normalizeURI(uri)] byUri => byUri && byUri[uri]
); );
export const makeSelectTotalPagesForChannel = (uri: string, pageSize: number = 10) => export const makeSelectTotalPagesForChannel = (uri: string, pageSize: number = 10) =>
createSelector( createSelector(
selectChannelClaimCounts, selectChannelClaimCounts,
byUri => byUri && byUri[uri] && Math.ceil(byUri[normalizeURI(uri)] / pageSize) byUri => byUri && byUri[uri] && Math.ceil(byUri[uri] / pageSize)
); );
export const makeSelectNsfwCountFromUris = (uris: Array<string>) => export const makeSelectNsfwCountFromUris = (uris: Array<string>) =>
@ -652,6 +579,27 @@ export const makeSelectNsfwCountFromUris = (uris: Array<string>) =>
}, 0) }, 0)
); );
export const makeSelectNsfwCountForChannel = (uri: string) =>
createSelector(
selectClaimsById,
selectAllClaimsByChannel,
selectCurrentChannelPage,
(byId, allClaims, page) => {
const byChannel = allClaims[uri] || {};
const claimIds = byChannel[page || 1];
if (!claimIds) return 0;
return claimIds.reduce((acc, claimId) => {
const claim = byId[claimId];
if (isClaimNsfw(claim)) {
return acc + 1;
}
return acc;
}, 0);
}
);
export const makeSelectOmittedCountForChannel = (uri: string) => export const makeSelectOmittedCountForChannel = (uri: string) =>
createSelector( createSelector(
makeSelectTotalItemsForChannel(uri), makeSelectTotalItemsForChannel(uri),
@ -700,29 +648,6 @@ export const makeSelectChannelForClaimUri = (uri: string, includePrefix: boolean
} }
); );
export const makeSelectChannelPermUrlForClaimUri = (uri: string, includePrefix: boolean = false) =>
createSelector(
makeSelectClaimForUri(uri),
(claim: ?Claim) => {
if (claim && claim.value_type === 'channel') {
return claim.permanent_url;
}
if (!claim || !claim.signing_channel || !claim.is_channel_signature_valid) {
return null;
}
return claim.signing_channel.permanent_url;
}
);
export const makeSelectMyChannelPermUrlForName = (name: string) =>
createSelector(
selectMyChannelClaims,
claims => {
const matchingClaim = claims && claims.find(claim => claim.name === name);
return matchingClaim ? matchingClaim.permanent_url : null;
}
);
export const makeSelectTagsForUri = (uri: string) => export const makeSelectTagsForUri = (uri: string) =>
createSelector( createSelector(
makeSelectMetadataForUri(uri), makeSelectMetadataForUri(uri),
@ -815,8 +740,8 @@ export const makeSelectMyStreamUrlsForPage = (page: number = 1) =>
createSelector( createSelector(
selectMyClaimUrisWithoutChannels, selectMyClaimUrisWithoutChannels,
urls => { urls => {
const start = (Number(page) - 1) * Number(CLAIM.PAGE_SIZE); const start = (Number(page) - 1) * Number(PAGE_SIZE);
const end = Number(page) * Number(CLAIM.PAGE_SIZE); const end = Number(page) * Number(PAGE_SIZE);
return urls && urls.length ? urls.slice(start, end) : []; return urls && urls.length ? urls.slice(start, end) : [];
} }
@ -826,97 +751,3 @@ export const selectMyStreamUrlsCount = createSelector(
selectMyClaimUrisWithoutChannels, selectMyClaimUrisWithoutChannels,
channels => channels.length channels => channels.length
); );
export const makeSelectTagInClaimOrChannelForUri = (uri: string, tag: string) =>
createSelector(
makeSelectClaimForUri(uri),
claim => {
const claimTags = (claim && claim.value && claim.value.tags) || [];
const channelTags =
(claim &&
claim.signing_channel &&
claim.signing_channel.value &&
claim.signing_channel.value.tags) ||
[];
return claimTags.includes(tag) || channelTags.includes(tag);
}
);
export const makeSelectClaimHasSource = (uri: string) =>
createSelector(
makeSelectClaimForUri(uri),
claim => {
if (!claim) {
return false;
}
return Boolean(claim.value.source);
}
);
export const makeSelectClaimIsStreamPlaceholder = (uri: string) =>
createSelector(
makeSelectClaimForUri(uri),
claim => {
if (!claim) {
return false;
}
return Boolean(claim.value_type === 'stream' && !claim.value.source);
}
);
export const makeSelectTotalStakedAmountForChannelUri = (uri: string) =>
createSelector(
makeSelectClaimForUri(uri),
claim => {
if (!claim || !claim.amount || !claim.meta || !claim.meta.support_amount) {
return 0;
}
return parseFloat(claim.amount) + parseFloat(claim.meta.support_amount) || 0;
}
);
export const makeSelectStakedLevelForChannelUri = (uri: string) =>
createSelector(
makeSelectTotalStakedAmountForChannelUri(uri),
amount => {
let level = 1;
switch (true) {
case amount >= CLAIM.LEVEL_2_STAKED_AMOUNT && amount < CLAIM.LEVEL_3_STAKED_AMOUNT:
level = 2;
break;
case amount >= CLAIM.LEVEL_3_STAKED_AMOUNT && amount < CLAIM.LEVEL_4_STAKED_AMOUNT:
level = 3;
break;
case amount >= CLAIM.LEVEL_4_STAKED_AMOUNT && amount < CLAIM.LEVEL_5_STAKED_AMOUNT:
level = 4;
break;
case amount >= CLAIM.LEVEL_5_STAKED_AMOUNT:
level = 5;
break;
}
return level;
}
);
export const selectUpdatingCollection = createSelector(
selectState,
state => state.updatingCollection
);
export const selectUpdateCollectionError = createSelector(
selectState,
state => state.updateCollectionError
);
export const selectCreatingCollection = createSelector(
selectState,
state => state.creatingCollection
);
export const selectCreateCollectionError = createSelector(
selectState,
state => state.createCollectionError
);

View file

@ -1,311 +0,0 @@
// @flow
import fromEntries from '@ungap/from-entries';
import { createSelector } from 'reselect';
import {
selectMyCollectionIds,
makeSelectClaimForUri,
selectClaimsByUri,
} from 'redux/selectors/claims';
import { parseURI } from 'lbryURI';
const selectState = (state: { collections: CollectionState }) => state.collections;
export const selectSavedCollectionIds = createSelector(
selectState,
collectionState => collectionState.saved
);
export const selectBuiltinCollections = createSelector(
selectState,
state => state.builtin
);
export const selectResolvedCollections = createSelector(
selectState,
state => state.resolved
);
export const selectMyUnpublishedCollections = createSelector(
selectState,
state => state.unpublished
);
export const selectMyEditedCollections = createSelector(
selectState,
state => state.edited
);
export const selectPendingCollections = createSelector(
selectState,
state => state.pending
);
export const makeSelectEditedCollectionForId = (id: string) =>
createSelector(
selectMyEditedCollections,
eLists => eLists[id]
);
export const makeSelectPendingCollectionForId = (id: string) =>
createSelector(
selectPendingCollections,
pending => pending[id]
);
export const makeSelectPublishedCollectionForId = (id: string) =>
createSelector(
selectResolvedCollections,
rLists => rLists[id]
);
export const makeSelectUnpublishedCollectionForId = (id: string) =>
createSelector(
selectMyUnpublishedCollections,
rLists => rLists[id]
);
export const makeSelectCollectionIsMine = (id: string) =>
createSelector(
selectMyCollectionIds,
selectMyUnpublishedCollections,
selectBuiltinCollections,
(publicIds, privateIds, builtinIds) => {
return Boolean(publicIds.includes(id) || privateIds[id] || builtinIds[id]);
}
);
export const selectMyPublishedCollections = createSelector(
selectResolvedCollections,
selectPendingCollections,
selectMyEditedCollections,
selectMyCollectionIds,
(resolved, pending, edited, myIds) => {
// all resolved in myIds, plus those in pending and edited
const myPublishedCollections = fromEntries(
Object.entries(pending).concat(
Object.entries(resolved).filter(
([key, val]) =>
myIds.includes(key) &&
// $FlowFixMe
!pending[key]
)
)
);
// now add in edited:
Object.entries(edited).forEach(([id, item]) => {
myPublishedCollections[id] = item;
});
return myPublishedCollections;
}
);
export const selectMyPublishedMixedCollections = createSelector(
selectMyPublishedCollections,
published => {
const myCollections = fromEntries(
// $FlowFixMe
Object.entries(published).filter(([key, collection]) => {
// $FlowFixMe
return collection.type === 'collection';
})
);
return myCollections;
}
);
export const selectMyPublishedPlaylistCollections = createSelector(
selectMyPublishedCollections,
published => {
const myCollections = fromEntries(
// $FlowFixMe
Object.entries(published).filter(([key, collection]) => {
// $FlowFixMe
return collection.type === 'playlist';
})
);
return myCollections;
}
);
export const makeSelectMyPublishedCollectionForId = (id: string) =>
createSelector(
selectMyPublishedCollections,
myPublishedCollections => myPublishedCollections[id]
);
// export const selectSavedCollections = createSelector(
// selectResolvedCollections,
// selectSavedCollectionIds,
// (resolved, myIds) => {
// const mySavedCollections = fromEntries(
// Object.entries(resolved).filter(([key, val]) => myIds.includes(key))
// );
// return mySavedCollections;
// }
// );
export const makeSelectIsResolvingCollectionForId = (id: string) =>
createSelector(
selectState,
state => {
return state.isResolvingCollectionById[id];
}
);
export const makeSelectCollectionForId = (id: string) =>
createSelector(
selectBuiltinCollections,
selectResolvedCollections,
selectMyUnpublishedCollections,
selectMyEditedCollections,
selectPendingCollections,
(bLists, rLists, uLists, eLists, pLists) => {
const collection = bLists[id] || uLists[id] || eLists[id] || pLists[id] || rLists[id];
return collection;
}
);
export const makeSelectClaimUrlInCollection = (url: string) =>
createSelector(
selectBuiltinCollections,
selectMyPublishedCollections,
selectMyUnpublishedCollections,
selectMyEditedCollections,
selectPendingCollections,
(bLists, myRLists, uLists, eLists, pLists) => {
const collections = [bLists, uLists, eLists, myRLists, pLists];
const itemsInCollections = [];
collections.map(list => {
Object.entries(list).forEach(([key, value]) => {
// $FlowFixMe
value.items.map(item => {
itemsInCollections.push(item);
});
});
});
return itemsInCollections.includes(url);
}
);
export const makeSelectCollectionForIdHasClaimUrl = (id: string, url: string) =>
createSelector(
makeSelectCollectionForId(id),
collection => collection && collection.items.includes(url)
);
export const makeSelectUrlsForCollectionId = (id: string) =>
createSelector(
makeSelectCollectionForId(id),
collection => collection && collection.items
);
export const makeSelectClaimIdsForCollectionId = (id: string) =>
createSelector(
makeSelectCollectionForId(id),
collection => {
const items = (collection && collection.items) || [];
const ids = items.map(item => {
const { claimId } = parseURI(item);
return claimId;
});
return ids;
}
);
export const makeSelectIndexForUrlInCollection = (url: string, id: string) =>
createSelector(
state => state.content.shuffleList,
makeSelectUrlsForCollectionId(id),
makeSelectClaimForUri(url),
(shuffleState, urls, claim) => {
const shuffleUrls = shuffleState && shuffleState.collectionId === id && shuffleState.newUrls;
const listUrls = shuffleUrls || urls;
const index = listUrls && listUrls.findIndex(u => u === url);
if (index > -1) {
return index;
} else if (claim) {
const index = listUrls && listUrls.findIndex(u => u === claim.permanent_url);
if (index > -1) return index;
return claim;
}
return null;
}
);
export const makeSelectPreviousUrlForCollectionAndUrl = (id: string, url: string) =>
createSelector(
state => state.content.shuffleList,
state => state.content.loopList,
makeSelectIndexForUrlInCollection(url, id),
makeSelectUrlsForCollectionId(id),
(shuffleState, loopState, index, urls) => {
const loopList = loopState && loopState.collectionId === id && loopState.loop;
const shuffleUrls = shuffleState && shuffleState.collectionId === id && shuffleState.newUrls;
if (index > -1) {
const listUrls = shuffleUrls || urls;
let nextUrl;
if (index === 0 && loopList) {
nextUrl = listUrls[listUrls.length - 1];
} else {
nextUrl = listUrls[index - 1];
}
return nextUrl || null;
} else {
return null;
}
}
);
export const makeSelectNextUrlForCollectionAndUrl = (id: string, url: string) =>
createSelector(
state => state.content.shuffleList,
state => state.content.loopList,
makeSelectIndexForUrlInCollection(url, id),
makeSelectUrlsForCollectionId(id),
(shuffleState, loopState, index, urls) => {
const loopList = loopState && loopState.collectionId === id && loopState.loop;
const shuffleUrls = shuffleState && shuffleState.collectionId === id && shuffleState.newUrls;
if (index > -1) {
const listUrls = shuffleUrls || urls;
// We'll get the next playble url
let remainingUrls = listUrls.slice(index + 1);
if (!remainingUrls.length && loopList) {
remainingUrls = listUrls.slice(0);
}
const nextUrl = remainingUrls && remainingUrls[0];
return nextUrl || null;
} else {
return null;
}
}
);
export const makeSelectNameForCollectionId = (id: string) =>
createSelector(
makeSelectCollectionForId(id),
collection => {
return (collection && collection.name) || '';
}
);
export const makeSelectCountForCollectionId = (id: string) =>
createSelector(
makeSelectCollectionForId(id),
collection => {
if (collection) {
if (collection.itemCount !== undefined) {
return collection.itemCount;
}
let itemCount = 0;
collection.items.map(item => {
if (item) {
itemCount += 1;
}
});
return itemCount;
}
return null;
}
);

View file

@ -40,22 +40,17 @@ export const selectIsStillEditing = createSelector(
export const selectPublishFormValues = createSelector( export const selectPublishFormValues = createSelector(
selectState, selectState,
state => state.settings,
selectIsStillEditing, selectIsStillEditing,
(publishState, settingsState, isStillEditing) => { (state, isStillEditing) => {
const { languages, ...formValues } = publishState; const { pendingPublish, language, languages, ...formValues } = state;
const language = languages && languages.length && languages[0];
const { clientSettings } = settingsState;
const { language: languageSet } = clientSettings;
let actualLanguage; let actualLanguage;
// Sets default if editing a claim with a set language // Sets default if editing a claim with a set language
if (!language && isStillEditing && languageSet) { if (!language && isStillEditing && languages && languages[0]) {
actualLanguage = languageSet; actualLanguage = languages[0];
} else { } else {
actualLanguage = language || languageSet || 'en'; actualLanguage = language || 'en';
} }
return { ...formValues, language: actualLanguage }; return { ...formValues, language: actualLanguage };
} }
); );

View file

@ -0,0 +1,47 @@
// @flow
import { createSelector } from 'reselect';
const selectState = (state: { tags: TagState }) => state.tags || {};
export const selectKnownTagsByName = createSelector(
selectState,
(state: TagState): KnownTags => state.knownTags
);
export const selectFollowedTagsList = createSelector(
selectState,
(state: TagState): Array<string> => state.followedTags.filter(tag => typeof tag === 'string')
);
export const selectFollowedTags = createSelector(
selectFollowedTagsList,
(followedTags: Array<string>): Array<Tag> =>
followedTags
.map(tag => ({ name: tag.toLowerCase() }))
.sort((a, b) => a.name.localeCompare(b.name))
);
export const selectUnfollowedTags = createSelector(
selectKnownTagsByName,
selectFollowedTagsList,
(tagsByName: KnownTags, followedTags: Array<string>): Array<Tag> => {
const followedTagsSet = new Set(followedTags);
let tagsToReturn = [];
Object.keys(tagsByName).forEach(key => {
if (!followedTagsSet.has(key)) {
const { name } = tagsByName[key];
tagsToReturn.push({ name: name.toLowerCase() });
}
});
return tagsToReturn;
}
);
export const makeSelectIsFollowingTag = (tag: string) =>
createSelector(
selectFollowedTags,
followedTags => {
return followedTags.some(followedTag => followedTag.name === tag.toLowerCase());
}
);

View file

@ -2,7 +2,6 @@ import { createSelector } from 'reselect';
import * as TRANSACTIONS from 'constants/transaction_types'; import * as TRANSACTIONS from 'constants/transaction_types';
import { PAGE_SIZE, LATEST_PAGE_SIZE } from 'constants/transaction_list'; import { PAGE_SIZE, LATEST_PAGE_SIZE } from 'constants/transaction_list';
import { selectClaimIdsByUri } from 'redux/selectors/claims'; import { selectClaimIdsByUri } from 'redux/selectors/claims';
import parseData from 'util/parse-data';
export const selectState = state => state.wallet || {}; export const selectState = state => state.wallet || {};
export const selectWalletState = selectState; export const selectWalletState = selectState;
@ -27,18 +26,12 @@ export const selectPendingSupportTransactions = createSelector(
state => state.pendingSupportTransactions state => state.pendingSupportTransactions
); );
export const selectPendingOtherTransactions = createSelector(
selectState,
state => state.pendingTxos
);
export const selectAbandonClaimSupportError = createSelector( export const selectAbandonClaimSupportError = createSelector(
selectState, selectState,
state => state.abandonClaimSupportError state => state.abandonClaimSupportError
); );
export const makeSelectPendingAmountByUri = uri => export const makeSelectPendingAmountByUri = (uri) => createSelector(
createSelector(
selectClaimIdsByUri, selectClaimIdsByUri,
selectPendingSupportTransactions, selectPendingSupportTransactions,
(claimIdsByUri, pendingSupports) => { (claimIdsByUri, pendingSupports) => {
@ -268,27 +261,6 @@ export const selectIsFetchingTransactions = createSelector(
state => state.fetchingTransactions state => state.fetchingTransactions
); );
/**
* CSV of 'selectTransactionItems'.
*/
export const selectTransactionsFile = createSelector(
selectTransactionItems,
transactions => {
if (!transactions || transactions.length === 0) {
// No data.
return undefined;
}
const parsed = parseData(transactions, 'csv');
if (!parsed) {
// Invalid data, or failed to parse.
return null;
}
return parsed;
}
);
export const selectIsSendingSupport = createSelector( export const selectIsSendingSupport = createSelector(
selectState, selectState,
state => state.sendingSupport state => state.sendingSupport
@ -356,27 +328,27 @@ export const selectTxoPageParams = createSelector(
export const selectTxoPage = createSelector( export const selectTxoPage = createSelector(
selectState, selectState,
state => (state.txoPage && state.txoPage.items) || [] state => (state.txoPage && state.txoPage.items) || [],
); );
export const selectTxoPageNumber = createSelector( export const selectTxoPageNumber = createSelector(
selectState, selectState,
state => (state.txoPage && state.txoPage.page) || 1 state => (state.txoPage && state.txoPage.page) || 1,
); );
export const selectTxoItemCount = createSelector( export const selectTxoItemCount = createSelector(
selectState, selectState,
state => (state.txoPage && state.txoPage.total_items) || 1 state => (state.txoPage && state.txoPage.total_items) || 1,
); );
export const selectFetchingTxosError = createSelector( export const selectFetchingTxosError = createSelector(
selectState, selectState,
state => state.fetchingTxosError state => state.fetchingTxosError,
); );
export const selectIsFetchingTxos = createSelector( export const selectIsFetchingTxos = createSelector(
selectState, selectState,
state => state.fetchingTxos state => state.fetchingTxos,
); );
export const makeSelectFilteredTransactionsForPage = (page = 1) => export const makeSelectFilteredTransactionsForPage = (page = 1) =>
@ -407,33 +379,3 @@ export const selectIsWalletReconnecting = createSelector(
selectState, selectState,
state => state.walletReconnecting state => state.walletReconnecting
); );
export const selectIsFetchingUtxoCounts = createSelector(
selectState,
state => state.fetchingUtxoCounts
);
export const selectIsConsolidatingUtxos = createSelector(
selectState,
state => state.consolidatingUtxos
);
export const selectIsMassClaimingTips = createSelector(
selectState,
state => state.massClaimingTips
);
export const selectPendingConsolidateTxid = createSelector(
selectState,
state => state.pendingConsolidateTxid
);
export const selectPendingMassClaimTxid = createSelector(
selectState,
state => state.pendingMassClaimTxid
);
export const selectUtxoCounts = createSelector(
selectState,
state => state.utxoCounts
);

View file

@ -1,61 +0,0 @@
// JSON parser
const parseJson = (data, filters = []) => {
const list = data.map(item => {
const temp = {};
// Apply filters
Object.entries(item).forEach(([key, value]) => {
if (!filters.includes(key)) temp[key] = value;
});
return temp;
});
// Beautify JSON
return JSON.stringify(list, null, '\t');
};
// CSV Parser
// No need for an external module:
// https://gist.github.com/btzr-io/55c3450ea3d709fc57540e762899fb85
const parseCsv = (data, filters = []) => {
// Get items for header
const getHeaders = item => {
const list = [];
// Apply filters
Object.entries(item).forEach(([key]) => {
if (!filters.includes(key)) list.push(key);
});
// return headers
return list.join(',');
};
// Get rows content
const getData = list =>
list
.map(item => {
const row = [];
// Apply filters
Object.entries(item).forEach(([key, value]) => {
if (!filters.includes(key)) row.push(value);
});
// return rows
return row.join(',');
})
.join('\n');
// Return CSV string
return `${getHeaders(data[0])} \n ${getData(data)}`;
};
const parseData = (data, format, filters = []) => {
// Check for validation
const valid = data && data[0] && format;
// Pick a format
const formats = {
csv: list => parseCsv(list, filters),
json: list => parseJson(list, filters),
};
// Return parsed data: JSON || CSV
return valid && formats[format] ? formats[format](data) : undefined;
};
export default parseData;

3294
yarn.lock

File diff suppressed because it is too large Load diff