Featured content
This commit is contained in:
parent
cb5067dce3
commit
393aa9129c
9 changed files with 219 additions and 274 deletions
|
@ -2,6 +2,29 @@ import * as types from 'constants/action_types'
|
||||||
import lbry from 'lbry'
|
import lbry from 'lbry'
|
||||||
import lbryio from 'lbryio';
|
import lbryio from 'lbryio';
|
||||||
|
|
||||||
|
export function doResolveUri(dispatch, uri) {
|
||||||
|
dispatch({
|
||||||
|
type: types.RESOLVE_URI_STARTED,
|
||||||
|
data: { uri }
|
||||||
|
})
|
||||||
|
|
||||||
|
lbry.resolve({uri: uri}).then((resolutionInfo) => {
|
||||||
|
const {
|
||||||
|
claim,
|
||||||
|
certificate,
|
||||||
|
} = resolutionInfo
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: types.RESOLVE_URI_COMPLETED,
|
||||||
|
data: {
|
||||||
|
uri,
|
||||||
|
claim,
|
||||||
|
certificate,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export function doFetchFeaturedContent() {
|
export function doFetchFeaturedContent() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState()
|
const state = getState()
|
||||||
|
@ -18,6 +41,10 @@ export function doFetchFeaturedContent() {
|
||||||
uris: Uris,
|
uris: Uris,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Object.keys(Uris).forEach((category) => {
|
||||||
|
Uris[category].forEach((uri) => doResolveUri(dispatch, uri))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const failure = () => {
|
const failure = () => {
|
||||||
|
|
7
ui/js/component/fileCardStream/index.js
Normal file
7
ui/js/component/fileCardStream/index.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {
|
||||||
|
connect
|
||||||
|
} from 'react-redux'
|
||||||
|
import FileCardStream from './view'
|
||||||
|
|
||||||
|
export default connect()(FileCardStream)
|
110
ui/js/component/fileCardStream/view.jsx
Normal file
110
ui/js/component/fileCardStream/view.jsx
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
import React from 'react';
|
||||||
|
import lbry from 'lbry.js';
|
||||||
|
import lbryuri from 'lbryuri.js';
|
||||||
|
import Link from 'component/link';
|
||||||
|
import {FileActions} from 'component/file-actions.js';
|
||||||
|
import {Thumbnail, TruncatedText, FilePrice} from 'component/common.js';
|
||||||
|
import UriIndicator from 'component/channel-indicator.js';
|
||||||
|
|
||||||
|
const FileCardStream = React.createClass({
|
||||||
|
_fileInfoSubscribeId: null,
|
||||||
|
_isMounted: null,
|
||||||
|
_metadata: null,
|
||||||
|
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
uri: React.PropTypes.string,
|
||||||
|
claimInfo: React.PropTypes.object,
|
||||||
|
outpoint: React.PropTypes.string,
|
||||||
|
hideOnRemove: React.PropTypes.bool,
|
||||||
|
hidePrice: React.PropTypes.bool,
|
||||||
|
obscureNsfw: React.PropTypes.bool
|
||||||
|
},
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
showNsfwHelp: false,
|
||||||
|
isHidden: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getDefaultProps: function() {
|
||||||
|
return {
|
||||||
|
obscureNsfw: !lbry.getClientSetting('showNsfw'),
|
||||||
|
hidePrice: false,
|
||||||
|
hasSignature: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
componentDidMount: function() {
|
||||||
|
this._isMounted = true;
|
||||||
|
if (this.props.hideOnRemove) {
|
||||||
|
this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.outpoint, this.onFileInfoUpdate);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
componentWillUnmount: function() {
|
||||||
|
if (this._fileInfoSubscribeId) {
|
||||||
|
lbry.fileInfoUnsubscribe(this.props.outpoint, this._fileInfoSubscribeId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onFileInfoUpdate: function(fileInfo) {
|
||||||
|
if (!fileInfo && this._isMounted && this.props.hideOnRemove) {
|
||||||
|
this.setState({
|
||||||
|
isHidden: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleMouseOver: function() {
|
||||||
|
this.setState({
|
||||||
|
hovered: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleMouseOut: function() {
|
||||||
|
this.setState({
|
||||||
|
hovered: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
if (this.state.isHidden) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uri = lbryuri.normalize(this.props.uri);
|
||||||
|
const metadata = this.props.metadata;
|
||||||
|
const isConfirmed = !!metadata;
|
||||||
|
const title = isConfirmed ? metadata.title : uri;
|
||||||
|
const obscureNsfw = this.props.obscureNsfw && isConfirmed && metadata.nsfw;
|
||||||
|
const primaryUrl = '?show=' + uri;
|
||||||
|
return (
|
||||||
|
<section className={ 'card card--small card--link ' + (obscureNsfw ? 'card--obscured ' : '') } onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}>
|
||||||
|
<div className="card__inner">
|
||||||
|
<a href={primaryUrl} className="card__link">
|
||||||
|
<div className="card__title-identity">
|
||||||
|
<h5 title={title}><TruncatedText lines={1}>{title}</TruncatedText></h5>
|
||||||
|
<div className="card__subtitle">
|
||||||
|
{ !this.props.hidePrice ? <span style={{float: "right"}}><FilePrice uri={this.props.uri} metadata={metadata} /></span> : null}
|
||||||
|
<UriIndicator uri={uri} metadata={metadata} contentType={this.props.contentType}
|
||||||
|
hasSignature={this.props.hasSignature} signatureIsValid={this.props.signatureIsValid} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="card__media" style={{ backgroundImage: "url('" + metadata.thumbnail + "')" }}></div>
|
||||||
|
<div className="card__content card__subtext card__subtext--two-lines">
|
||||||
|
<TruncatedText lines={2}>
|
||||||
|
{isConfirmed
|
||||||
|
? metadata.description
|
||||||
|
: <span className="empty">This file is pending confirmation.</span>}
|
||||||
|
</TruncatedText>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{this.state.showNsfwHelp && this.state.hovered
|
||||||
|
? <div className='card-overlay'>
|
||||||
|
<p>
|
||||||
|
This content is Not Safe For Work.
|
||||||
|
To view adult content, please change your <Link className="button-text" href="?settings" label="Settings" />.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
: null}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default FileCardStream
|
|
@ -2,9 +2,13 @@ import React from 'react'
|
||||||
import {
|
import {
|
||||||
connect
|
connect
|
||||||
} from 'react-redux'
|
} from 'react-redux'
|
||||||
|
import {
|
||||||
|
selectResolvedUris,
|
||||||
|
} from 'selectors/content'
|
||||||
import FileTile from './view'
|
import FileTile from './view'
|
||||||
|
|
||||||
const select = (state) => ({
|
const select = (state) => ({
|
||||||
|
resolvedUris: selectResolvedUris(state),
|
||||||
})
|
})
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
|
|
|
@ -2,283 +2,30 @@ import React from 'react';
|
||||||
import lbry from 'lbry.js';
|
import lbry from 'lbry.js';
|
||||||
import lbryuri from 'lbryuri.js';
|
import lbryuri from 'lbryuri.js';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import {FileActions} from 'component/file-actions.js';
|
import FileCardStream from 'component/fileCardStream'
|
||||||
import {Thumbnail, TruncatedText, FilePrice} from 'component/common.js';
|
import FileTileStream from 'component/fileTileStream'
|
||||||
import UriIndicator from 'component/channel-indicator.js';
|
import FileActions from 'component/fileActions';
|
||||||
|
|
||||||
/*should be merged into FileTile once FileTile is refactored to take a single id*/
|
class FileTile extends React.Component {
|
||||||
export let FileTileStream = React.createClass({
|
render() {
|
||||||
_fileInfoSubscribeId: null,
|
const {
|
||||||
_isMounted: null,
|
displayStyle,
|
||||||
|
uri,
|
||||||
|
claim,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
propTypes: {
|
if(!claim) {
|
||||||
uri: React.PropTypes.string,
|
if (displayStyle == 'card') {
|
||||||
metadata: React.PropTypes.object,
|
return <FileCardStream uri={uri} />
|
||||||
contentType: React.PropTypes.string.isRequired,
|
|
||||||
outpoint: React.PropTypes.string,
|
|
||||||
hasSignature: React.PropTypes.bool,
|
|
||||||
signatureIsValid: React.PropTypes.bool,
|
|
||||||
hideOnRemove: React.PropTypes.bool,
|
|
||||||
hidePrice: React.PropTypes.bool,
|
|
||||||
obscureNsfw: React.PropTypes.bool
|
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
showNsfwHelp: false,
|
|
||||||
isHidden: false,
|
|
||||||
}
|
}
|
||||||
},
|
return null
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
|
||||||
obscureNsfw: !lbry.getClientSetting('showNsfw'),
|
|
||||||
hidePrice: false,
|
|
||||||
hasSignature: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
componentDidMount: function() {
|
|
||||||
this._isMounted = true;
|
|
||||||
if (this.props.hideOnRemove) {
|
|
||||||
this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.outpoint, this.onFileInfoUpdate);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
componentWillUnmount: function() {
|
|
||||||
if (this._fileInfoSubscribeId) {
|
|
||||||
lbry.fileInfoUnsubscribe(this.props.outpoint, this._fileInfoSubscribeId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onFileInfoUpdate: function(fileInfo) {
|
|
||||||
if (!fileInfo && this._isMounted && this.props.hideOnRemove) {
|
|
||||||
this.setState({
|
|
||||||
isHidden: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleMouseOver: function() {
|
|
||||||
if (this.props.obscureNsfw && this.props.metadata && this.props.metadata.nsfw) {
|
|
||||||
this.setState({
|
|
||||||
showNsfwHelp: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleMouseOut: function() {
|
|
||||||
if (this.state.showNsfwHelp) {
|
|
||||||
this.setState({
|
|
||||||
showNsfwHelp: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
if (this.state.isHidden) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const uri = lbryuri.normalize(this.props.uri);
|
return displayStyle == 'card' ?
|
||||||
const metadata = this.props.metadata;
|
<FileCardStream uri={uri} />
|
||||||
const isConfirmed = !!metadata;
|
:
|
||||||
const title = isConfirmed ? metadata.title : uri;
|
<FileTileStream uri={uri} key={uri} />
|
||||||
const obscureNsfw = this.props.obscureNsfw && isConfirmed && metadata.nsfw;
|
|
||||||
const primaryUrl = "?show=" + uri;
|
|
||||||
return (
|
|
||||||
<section className={ 'file-tile card ' + (obscureNsfw ? 'card--obscured ' : '') } onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}>
|
|
||||||
<a href={primaryUrl} className="card__link">
|
|
||||||
<div className={"card__inner file-tile__row"}>
|
|
||||||
<div className="card__media"
|
|
||||||
style={{ backgroundImage: "url('" + (metadata && metadata.thumbnail ? metadata.thumbnail : lbry.imagePath('default-thumb.svg')) + "')" }}>
|
|
||||||
</div>
|
|
||||||
<div className="file-tile__content">
|
|
||||||
<div className="card__title-primary">
|
|
||||||
{ !this.props.hidePrice
|
|
||||||
? <FilePrice uri={this.props.uri} />
|
|
||||||
: null}
|
|
||||||
<div className="meta">{uri}</div>
|
|
||||||
<h3><TruncatedText lines={1}>{title}</TruncatedText></h3>
|
|
||||||
</div>
|
|
||||||
<div className="card__content card__subtext">
|
|
||||||
<TruncatedText lines={3}>
|
|
||||||
{isConfirmed
|
|
||||||
? metadata.description
|
|
||||||
: <span className="empty">This file is pending confirmation.</span>}
|
|
||||||
</TruncatedText>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
{this.state.showNsfwHelp
|
|
||||||
? <div className='card-overlay'>
|
|
||||||
<p>
|
|
||||||
This content is Not Safe For Work.
|
|
||||||
To view adult content, please change your <Link className="button-text" href="?settings" label="Settings" />.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
: null}
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export let FileCardStream = React.createClass({
|
export default FileTile
|
||||||
_fileInfoSubscribeId: null,
|
|
||||||
_isMounted: null,
|
|
||||||
_metadata: null,
|
|
||||||
|
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
uri: React.PropTypes.string,
|
|
||||||
claimInfo: React.PropTypes.object,
|
|
||||||
outpoint: React.PropTypes.string,
|
|
||||||
hideOnRemove: React.PropTypes.bool,
|
|
||||||
hidePrice: React.PropTypes.bool,
|
|
||||||
obscureNsfw: React.PropTypes.bool
|
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
showNsfwHelp: false,
|
|
||||||
isHidden: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
|
||||||
obscureNsfw: !lbry.getClientSetting('showNsfw'),
|
|
||||||
hidePrice: false,
|
|
||||||
hasSignature: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
componentDidMount: function() {
|
|
||||||
this._isMounted = true;
|
|
||||||
if (this.props.hideOnRemove) {
|
|
||||||
this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.outpoint, this.onFileInfoUpdate);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
componentWillUnmount: function() {
|
|
||||||
if (this._fileInfoSubscribeId) {
|
|
||||||
lbry.fileInfoUnsubscribe(this.props.outpoint, this._fileInfoSubscribeId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onFileInfoUpdate: function(fileInfo) {
|
|
||||||
if (!fileInfo && this._isMounted && this.props.hideOnRemove) {
|
|
||||||
this.setState({
|
|
||||||
isHidden: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleMouseOver: function() {
|
|
||||||
this.setState({
|
|
||||||
hovered: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleMouseOut: function() {
|
|
||||||
this.setState({
|
|
||||||
hovered: false,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
if (this.state.isHidden) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uri = lbryuri.normalize(this.props.uri);
|
|
||||||
const metadata = this.props.metadata;
|
|
||||||
const isConfirmed = !!metadata;
|
|
||||||
const title = isConfirmed ? metadata.title : uri;
|
|
||||||
const obscureNsfw = this.props.obscureNsfw && isConfirmed && metadata.nsfw;
|
|
||||||
const primaryUrl = '?show=' + uri;
|
|
||||||
return (
|
|
||||||
<section className={ 'card card--small card--link ' + (obscureNsfw ? 'card--obscured ' : '') } onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}>
|
|
||||||
<div className="card__inner">
|
|
||||||
<a href={primaryUrl} className="card__link">
|
|
||||||
<div className="card__title-identity">
|
|
||||||
<h5 title={title}><TruncatedText lines={1}>{title}</TruncatedText></h5>
|
|
||||||
<div className="card__subtitle">
|
|
||||||
{ !this.props.hidePrice ? <span style={{float: "right"}}><FilePrice uri={this.props.uri} metadata={metadata} /></span> : null}
|
|
||||||
<UriIndicator uri={uri} metadata={metadata} contentType={this.props.contentType}
|
|
||||||
hasSignature={this.props.hasSignature} signatureIsValid={this.props.signatureIsValid} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="card__media" style={{ backgroundImage: "url('" + metadata.thumbnail + "')" }}></div>
|
|
||||||
<div className="card__content card__subtext card__subtext--two-lines">
|
|
||||||
<TruncatedText lines={2}>
|
|
||||||
{isConfirmed
|
|
||||||
? metadata.description
|
|
||||||
: <span className="empty">This file is pending confirmation.</span>}
|
|
||||||
</TruncatedText>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
{this.state.showNsfwHelp && this.state.hovered
|
|
||||||
? <div className='card-overlay'>
|
|
||||||
<p>
|
|
||||||
This content is Not Safe For Work.
|
|
||||||
To view adult content, please change your <Link className="button-text" href="?settings" label="Settings" />.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
: null}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let FileTile = React.createClass({
|
|
||||||
_isMounted: false,
|
|
||||||
_isResolvePending: false,
|
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
uri: React.PropTypes.string.isRequired,
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
outpoint: null,
|
|
||||||
claimInfo: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: function(uri) {
|
|
||||||
this._isResolvePending = true;
|
|
||||||
lbry.resolve({uri: uri}).then((resolutionInfo) => {
|
|
||||||
this._isResolvePending = false;
|
|
||||||
if (this._isMounted && resolutionInfo && resolutionInfo.claim && resolutionInfo.claim.value &&
|
|
||||||
resolutionInfo.claim.value.stream && resolutionInfo.claim.value.stream.metadata) {
|
|
||||||
// In case of a failed lookup, metadata will be null, in which case the component will never display
|
|
||||||
this.setState({
|
|
||||||
claimInfo: resolutionInfo.claim,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
componentWillReceiveProps: function(nextProps) {
|
|
||||||
if (nextProps.uri != this.props.uri) {
|
|
||||||
this.setState(this.getInitialState());
|
|
||||||
this.resolve(nextProps.uri);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
componentDidMount: function() {
|
|
||||||
this._isMounted = true;
|
|
||||||
this.resolve(this.props.uri);
|
|
||||||
},
|
|
||||||
componentWillUnmount: function() {
|
|
||||||
this._isMounted = false;
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
if (!this.state.claimInfo) {
|
|
||||||
if (this.props.displayStyle == 'card') {
|
|
||||||
return <FileCardStream outpoint={null} metadata={{title: this.props.uri, description: "Loading..."}} contentType={null} hidePrice={true}
|
|
||||||
hasSignature={false} signatureIsValid={false} uri={this.props.uri} />
|
|
||||||
}
|
|
||||||
if (this.props.showEmpty)
|
|
||||||
{
|
|
||||||
return this._isResolvePending ?
|
|
||||||
<BusyMessage message="Loading magic decentralized data" /> :
|
|
||||||
<div className="empty">{lbryuri.normalize(this.props.uri)} is unclaimed. <Link label="Put something here" href="?publish" /></div>;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {txid, nout, has_signature, signature_is_valid,
|
|
||||||
value: {stream: {metadata, source: {contentType}}}} = this.state.claimInfo;
|
|
||||||
|
|
||||||
return this.props.displayStyle == 'card' ?
|
|
||||||
<FileCardStream outpoint={txid + ':' + nout} metadata={metadata} contentType={contentType}
|
|
||||||
hasSignature={has_signature} signatureIsValid={signature_is_valid} {... this.props}/> :
|
|
||||||
<FileTileStream outpoint={txid + ':' + nout} metadata={metadata} contentType={contentType}
|
|
||||||
hasSignature={has_signature} signatureIsValid={signature_is_valid} {... this.props} />;
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -37,3 +37,5 @@ export const SEND_TRANSACTION_FAILED = 'SEND_TRANSACTION_FAILED'
|
||||||
// Content
|
// Content
|
||||||
export const FETCH_FEATURED_CONTENT_STARTED = 'FETCH_FEATURED_CONTENT_STARTED'
|
export const FETCH_FEATURED_CONTENT_STARTED = 'FETCH_FEATURED_CONTENT_STARTED'
|
||||||
export const FETCH_FEATURED_CONTENT_COMPLETED = 'FETCH_FEATURED_CONTENT_COMPLETED'
|
export const FETCH_FEATURED_CONTENT_COMPLETED = 'FETCH_FEATURED_CONTENT_COMPLETED'
|
||||||
|
export const RESOLVE_URI_STARTED = 'RESOLVE_URI_STARTED'
|
||||||
|
export const RESOLVE_URI_COMPLETED = 'RESOLVE_URI_COMPLETED'
|
||||||
|
|
|
@ -11,6 +11,7 @@ const communityCategoryToolTipText = ('Community Content is a public space where
|
||||||
const FeaturedCategory = (props) => {
|
const FeaturedCategory = (props) => {
|
||||||
const {
|
const {
|
||||||
category,
|
category,
|
||||||
|
resolvedUris,
|
||||||
names,
|
names,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,48 @@ reducers[types.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reducers[types.RESOLVE_URI_STARTED] = function(state, action) {
|
||||||
|
const {
|
||||||
|
uri
|
||||||
|
} = action.data
|
||||||
|
|
||||||
|
const oldResolving = state.resolvingUris || []
|
||||||
|
const newResolving = Object.assign([], oldResolving)
|
||||||
|
if (newResolving.indexOf(uri) == -1) newResolving.push(uri)
|
||||||
|
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
resolvingUris: newResolving
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
reducers[types.RESOLVE_URI_COMPLETED] = function(state, action) {
|
||||||
|
const {
|
||||||
|
uri,
|
||||||
|
claim,
|
||||||
|
certificate,
|
||||||
|
} = action.data
|
||||||
|
const resolvedUris = Object.assign({}, state.resolvedUris)
|
||||||
|
const resolvingUris = state.resolvingUris
|
||||||
|
const index = state.resolvingUris.indexOf(uri)
|
||||||
|
const newResolvingUris = [
|
||||||
|
...resolvingUris.slice(0, index),
|
||||||
|
...resolvingUris.slice(index + 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
resolvedUris[uri] = {
|
||||||
|
claim: claim,
|
||||||
|
certificate: certificate,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const newState = Object.assign({}, state, {
|
||||||
|
resolvedUris: resolvedUris,
|
||||||
|
resolvingUris: newResolvingUris,
|
||||||
|
})
|
||||||
|
|
||||||
|
return Object.assign({}, state, newState)
|
||||||
|
}
|
||||||
|
|
||||||
export default function reducer(state = defaultState, action) {
|
export default function reducer(state = defaultState, action) {
|
||||||
const handler = reducers[action.type];
|
const handler = reducers[action.type];
|
||||||
if (handler) return handler(state, action);
|
if (handler) return handler(state, action);
|
||||||
|
|
|
@ -35,3 +35,8 @@ export const shouldFetchFeaturedContent = createSelector(
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const selectResolvedUris = createSelector(
|
||||||
|
_selectState,
|
||||||
|
(state) => state.resolvedUris || {}
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue