A bunch of improvements and broken the back of the file rendering code now

This commit is contained in:
6ea86b96 2017-04-29 16:50:29 +07:00 committed by Jeremy Kauffman
parent a77370afc9
commit e88f06c17c
23 changed files with 385 additions and 118 deletions

View file

@ -0,0 +1,21 @@
import * as types from 'constants/action_types'
import lbry from 'lbry'
export function doFetchUriAvailability(uri) {
return function(dispatch, getState) {
dispatch({
type: types.FETCH_AVAILABILITY_STARTED,
data: { uri }
})
lbry.get_availability({ uri }, (availability) => {
dispatch({
type: types.FETCH_AVAILABILITY_COMPLETED',
data: {
availability,
uri,
}
})
}
}
}

View file

@ -1,6 +1,7 @@
import * as types from 'constants/action_types' import * as types from 'constants/action_types'
import lbry from 'lbry' import lbry from 'lbry'
import lbryio from 'lbryio' import lbryio from 'lbryio'
import lbryuri from 'lbryuri'
import { import {
selectCurrentUri, selectCurrentUri,
} from 'selectors/app' } from 'selectors/app'
@ -113,7 +114,9 @@ export function doFetchFeaturedContent() {
}) })
Object.keys(Uris).forEach((category) => { Object.keys(Uris).forEach((category) => {
Uris[category].forEach((uri) => dispatch(doResolveUri(uri))) Uris[category].forEach((uri) => {
dispatch(doResolveUri(lbryuri.normalize(uri)))
})
}) })
} }

View file

@ -32,7 +32,7 @@ export function doSearchContent(query) {
contentName: result.name, contentName: result.name,
claimId: result.channel_id || result.claim_id, claimId: result.channel_id || result.claim_id,
}) })
dispatch(doResolveUri(uri.split('://')[1])) dispatch(doResolveUri(uri))
}) })
dispatch({ dispatch({

View file

@ -0,0 +1,21 @@
import React from 'react'
import {
connect,
} from 'react-redux'
import {
selectObscureNsfw,
selectHidePrice,
selectHasSignature,
} from 'selectors/app'
import FileActions from './view'
const select = (state) => ({
obscureNsfw: selectObscureNsfw(state),
hidePrice: selectHidePrice(state),
hasSignature: selectHasSignature(state),
})
const perform = {
}
export default connect(select, perform)(FileActions)

View file

@ -1,16 +1,16 @@
import React from 'react'; import React from 'react';
import lbry from '../lbry.js'; import lbry from 'lbry';
import lbryuri from '../lbryuri.js'; import lbryuri from 'lbryuri';
import {Icon, FilePrice} from 'component/common';
import {Modal} from 'component/modal';
import {FormField} from 'component/form';
import Link from 'component/link'; import Link from 'component/link';
import {Icon, FilePrice} from '../component/common.js'; import {ToolTip} from 'component/tooltip';
import Modal from './modal.js'; import {DropDownMenu, DropDownMenuItem} from 'component/menu';
import FormField from './form.js';
import {ToolTip} from '../component/tooltip.js';
import {DropDownMenu, DropDownMenuItem} from './menu.js';
const {shell} = require('electron'); const {shell} = require('electron');
let FileActionsRow = React.createClass({ const FileActionsRow = React.createClass({
_isMounted: false, _isMounted: false,
_fileInfoSubscribeId: null, _fileInfoSubscribeId: null,
@ -192,7 +192,7 @@ let FileActionsRow = React.createClass({
} }
}); });
export let FileActions = React.createClass({ const FileActions = React.createClass({
_isMounted: false, _isMounted: false,
_fileInfoSubscribeId: null, _fileInfoSubscribeId: null,
@ -268,3 +268,5 @@ export let FileActions = React.createClass({
</section>); </section>);
} }
}); });
export default FileActions

View file

@ -5,13 +5,40 @@ import {
import { import {
doNavigate, doNavigate,
} from 'actions/app' } from 'actions/app'
import {
selectHidePrice,
selectObscureNsfw,
} from 'selectors/app'
import {
makeSelectClaimForUri,
makeSelectSourceForUri,
makeSelectMetadataForUri,
} from 'selectors/claims'
import {
makeSelectFileInfoForUri,
} from 'selectors/file_info'
import FileCardStream from './view' import FileCardStream from './view'
const select = (state) => ({ const makeSelect = () => {
}) const selectClaimForUri = makeSelectClaimForUri()
const selectFileInfoForUri = makeSelectFileInfoForUri()
const selectMetadataForUri = makeSelectMetadataForUri()
const selectSourceForUri = makeSelectSourceForUri()
const select = (state, props) => ({
claim: selectClaimForUri(state, props),
fileInfo: selectFileInfoForUri(state, props),
hidePrice: selectHidePrice(state),
obscureNsfw: selectObscureNsfw(state),
hasSignature: false,
metadata: selectMetadataForUri(state, props),
source: selectSourceForUri(state, props),
})
return select
}
const perform = (dispatch) => ({ const perform = (dispatch) => ({
navigate: (path) => dispatch(doNavigate(path)), navigate: (path) => dispatch(doNavigate(path)),
}) })
export default connect(select, perform)(FileCardStream) export default connect(makeSelect, perform)(FileCardStream)

View file

@ -2,70 +2,63 @@ 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 {Thumbnail, TruncatedText, FilePrice} from 'component/common';
import {Thumbnail, TruncatedText, FilePrice} from 'component/common.js'; import UriIndicator from 'component/channel-indicator';
import UriIndicator from 'component/channel-indicator.js';
const FileCardStream = React.createClass({ class FileCardStream extends React.Component {
_fileInfoSubscribeId: null, constructor(props) {
_isMounted: null, super(props)
_metadata: null, this._fileInfoSubscribeId = null
this._isMounted = null
this._metadata = null
propTypes: { this.state = {
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, showNsfwHelp: false,
isHidden: false, isHidden: false,
} }
},
getDefaultProps: function() {
return {
obscureNsfw: !lbry.getClientSetting('showNsfw'),
hidePrice: false,
hasSignature: false,
} }
},
componentDidMount: function() { componentDidMount() {
this._isMounted = true; this._isMounted = true;
if (this.props.hideOnRemove) { if (this.props.hideOnRemove) {
this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.outpoint, this.onFileInfoUpdate); this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.outpoint, this.onFileInfoUpdate);
} }
}, }
componentWillUnmount: function() {
componentWillUnmount() {
if (this._fileInfoSubscribeId) { if (this._fileInfoSubscribeId) {
lbry.fileInfoUnsubscribe(this.props.outpoint, this._fileInfoSubscribeId); lbry.fileInfoUnsubscribe(this.props.outpoint, this._fileInfoSubscribeId);
} }
}, }
onFileInfoUpdate: function(fileInfo) {
onFileInfoUpdate(fileInfo) {
if (!fileInfo && this._isMounted && this.props.hideOnRemove) { if (!fileInfo && this._isMounted && this.props.hideOnRemove) {
this.setState({ this.setState({
isHidden: true isHidden: true
}); });
} }
}, }
handleMouseOver: function() {
handleMouseOver() {
this.setState({ this.setState({
hovered: true, hovered: true,
}); });
}, }
handleMouseOut: function() {
handleMouseOut() {
this.setState({ this.setState({
hovered: false, hovered: false,
}); });
}, }
render: function() {
render() {
if (this.state.isHidden) { if (this.state.isHidden) {
return null; return null;
} }
if (!this.props.metadata) {
return null
}
const uri = lbryuri.normalize(this.props.uri); const uri = lbryuri.normalize(this.props.uri);
const metadata = this.props.metadata; const metadata = this.props.metadata;
const isConfirmed = !!metadata; const isConfirmed = !!metadata;
@ -73,13 +66,13 @@ const FileCardStream = React.createClass({
const obscureNsfw = this.props.obscureNsfw && isConfirmed && metadata.nsfw; const obscureNsfw = this.props.obscureNsfw && isConfirmed && metadata.nsfw;
const primaryUrl = 'show=' + uri; const primaryUrl = 'show=' + uri;
return ( return (
<section className={ 'card card--small card--link ' + (obscureNsfw ? 'card--obscured ' : '') } onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}> <section className={ 'card card--small card--link ' + (obscureNsfw ? 'card--obscured ' : '') } onMouseEnter={this.handleMouseOver.bind(this)} onMouseLeave={this.handleMouseOut.bind(this)}>
<div className="card__inner"> <div className="card__inner">
<a href="#" onClick={() => this.props.navigate(primaryUrl)} className="card__link"> <a href="#" onClick={() => this.props.navigate(primaryUrl)} className="card__link">
<div className="card__title-identity"> <div className="card__title-identity">
<h5 title={title}><TruncatedText lines={1}>{title}</TruncatedText></h5> <h5 title={title}><TruncatedText lines={1}>{title}</TruncatedText></h5>
<div className="card__subtitle"> <div className="card__subtitle">
{ !this.props.hidePrice ? <span style={{float: "right"}}><FilePrice uri={this.props.uri} metadata={metadata} /></span> : null} { !this.props.hidePrice ? <span style={{float: "right"}}><FilePrice uri={this.props.uri} /></span> : null}
<UriIndicator uri={uri} metadata={metadata} contentType={this.props.contentType} <UriIndicator uri={uri} metadata={metadata} contentType={this.props.contentType}
hasSignature={this.props.hasSignature} signatureIsValid={this.props.signatureIsValid} /> hasSignature={this.props.hasSignature} signatureIsValid={this.props.signatureIsValid} />
</div> </div>
@ -105,6 +98,6 @@ const FileCardStream = React.createClass({
</section> </section>
); );
} }
}); }
export default FileCardStream export default FileCardStream

View file

@ -79,9 +79,7 @@ const FileList = React.createClass({
const uri = lbryuri.build({contentName: name, channelName: channel_name}); const uri = lbryuri.build({contentName: name, channelName: channel_name});
seenUris[name] = true; seenUris[name] = true;
content.push(<FileTileStream key={outpoint} outpoint={outpoint} uri={uri} hideOnRemove={true} content.push(<FileTileStream key={outpoint} uri={uri} hideOnRemove={true} />)
hidePrice={this.props.hidePrices} metadata={streamMetadata} contentType={mime_type}
hasSignature={has_signature} signatureIsValid={signature_is_valid} />);
} }
return ( return (

View file

@ -3,15 +3,25 @@ import {
connect connect
} from 'react-redux' } from 'react-redux'
import { import {
selectClaimsByUri, makeSelectClaimForUri,
} from 'selectors/claims' } from 'selectors/claims'
import {
makeSelectFileInfoForUri,
} from 'selectors/file_info'
import FileTile from './view' import FileTile from './view'
const select = (state) => ({ const makeSelect = () => {
claims: (uri) => selectClaimsByUri(state)[uri], const selectClaimForUri = makeSelectClaimForUri()
}) const selectFileInfoForUri = makeSelectFileInfoForUri()
const select = (state, props) => ({
claim: selectClaimForUri(state, props),
fileInfo: selectFileInfoForUri(state, props),
})
return select
}
const perform = (dispatch) => ({ const perform = (dispatch) => ({
}) })
export default connect(select, perform)(FileTile) export default connect(makeSelect, perform)(FileTile)

View file

@ -10,11 +10,11 @@ class FileTile extends React.Component {
render() { render() {
const { const {
displayStyle, displayStyle,
uri uri,
claim,
} = this.props } = this.props
const claimInfo = this.props.claims(uri)
if(!claimInfo) { if(!claim) {
if (displayStyle == 'card') { if (displayStyle == 'card') {
return <FileCardStream uri={uri} /> return <FileCardStream uri={uri} />
} }

View file

@ -5,13 +5,46 @@ import {
import { import {
doNavigate, doNavigate,
} from 'actions/app' } from 'actions/app'
import {
makeSelectClaimForUri,
makeSelectSourceForUri,
makeSelectMetadataForUri,
} from 'selectors/claims'
import {
makeSelectFileInfoForUri,
} from 'selectors/file_info'
import {
makeSelectFetchingAvailabilityForUri,
makeSelectAvailabilityForUri,
} from 'selectors/availability'
import {
selectObscureNsfw,
} from 'selectors/app'
import FileTileStream from './view' import FileTileStream from './view'
const select = (state) => ({ const makeSelect = () => {
}) const selectClaimForUri = makeSelectClaimForUri()
const selectFileInfoForUri = makeSelectFileInfoForUri()
const selectFetchingAvailabilityForUri = makeSelectFetchingAvailabilityForUri()
const selectAvailabilityForUri = makeSelectAvailabilityForUri()
const selectMetadataForUri = makeSelectMetadataForUri()
const selectSourceForUri = makeSelectSourceForUri()
const select = (state, props) => ({
claim: selectClaimForUri(state, props),
fileInfo: selectFileInfoForUri(state, props),
fetchingAvailability: selectFetchingAvailabilityForUri(state, props),
selectAvailabilityForUri: selectAvailabilityForUri(state, props),
obscureNswf: selectObscureNsfw(state),
metadata: selectMetadataForUri(state, props),
source: selectSourceForUri(state, props),
})
return select
}
const perform = (dispatch) => ({ const perform = (dispatch) => ({
navigate: (path) => dispatch(doNavigate(path)) navigate: (path) => dispatch(doNavigate(path))
}) })
export default connect(select, perform)(FileTileStream) export default connect(makeSelect, perform)(FileTileStream)

View file

@ -2,86 +2,76 @@ 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 { import FileActions from 'component/fileActions';
FileActions
} from 'component/file-actions.js';
import {Thumbnail, TruncatedText, FilePrice} from 'component/common.js'; import {Thumbnail, TruncatedText, FilePrice} from 'component/common.js';
import UriIndicator from 'component/channel-indicator.js'; import UriIndicator from 'component/channel-indicator.js';
/*should be merged into FileTile once FileTile is refactored to take a single id*/ /*should be merged into FileTile once FileTile is refactored to take a single id*/
const FileTileStream = React.createClass({ class FileTileStream extends React.Component {
_fileInfoSubscribeId: null, constructor(props) {
_isMounted: null, super(props)
this._fileInfoSubscribeId = null
propTypes: { this._isMounted = null
uri: React.PropTypes.string, this.state = {
metadata: React.PropTypes.object,
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, showNsfwHelp: false,
isHidden: false, isHidden: false,
} }
},
getDefaultProps: function() {
return {
obscureNsfw: !lbry.getClientSetting('showNsfw'),
hidePrice: false,
hasSignature: false,
} }
},
componentDidMount: function() { componentDidMount() {
this._isMounted = true; this._isMounted = true;
if (this.props.hideOnRemove) { if (this.props.hideOnRemove) {
this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.outpoint, this.onFileInfoUpdate); this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.outpoint, this.onFileInfoUpdate);
} }
}, }
componentWillUnmount: function() {
componentWillUnmount() {
if (this._fileInfoSubscribeId) { if (this._fileInfoSubscribeId) {
lbry.fileInfoUnsubscribe(this.props.outpoint, this._fileInfoSubscribeId); lbry.fileInfoUnsubscribe(this.props.outpoint, this._fileInfoSubscribeId);
} }
}, }
onFileInfoUpdate: function(fileInfo) {
onFileInfoUpdate(fileInfo) {
if (!fileInfo && this._isMounted && this.props.hideOnRemove) { if (!fileInfo && this._isMounted && this.props.hideOnRemove) {
this.setState({ this.setState({
isHidden: true isHidden: true
}); });
} }
}, }
handleMouseOver: function() {
handleMouseOver() {
if (this.props.obscureNsfw && this.props.metadata && this.props.metadata.nsfw) { if (this.props.obscureNsfw && this.props.metadata && this.props.metadata.nsfw) {
this.setState({ this.setState({
showNsfwHelp: true, showNsfwHelp: true,
}); });
} }
}, }
handleMouseOut: function() {
handleMouseOut() {
if (this.state.showNsfwHelp) { if (this.state.showNsfwHelp) {
this.setState({ this.setState({
showNsfwHelp: false, showNsfwHelp: false,
}); });
} }
}, }
render: function() {
render() {
if (this.state.isHidden) { if (this.state.isHidden) {
return null; return null;
} }
const {
metadata,
navigate,
} = this.props
const uri = lbryuri.normalize(this.props.uri); const uri = lbryuri.normalize(this.props.uri);
const metadata = this.props.metadata;
const isConfirmed = !!metadata; const isConfirmed = !!metadata;
const title = isConfirmed ? metadata.title : uri; const title = isConfirmed ? metadata.title : uri;
const obscureNsfw = this.props.obscureNsfw && isConfirmed && metadata.nsfw; const obscureNsfw = this.props.obscureNsfw && isConfirmed && metadata.nsfw;
const { navigate } = this.props
return ( return (
<section className={ 'file-tile card ' + (obscureNsfw ? 'card--obscured ' : '') } onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}> <section className={ 'file-tile card ' + (obscureNsfw ? 'card--obscured ' : '') } onMouseEnter={this.handleMouseOver.bind(this)} onMouseLeave={this.handleMouseOut.bind(this)}>
<div className={"row-fluid card__inner file-tile__row"}> <div className={"row-fluid card__inner file-tile__row"}>
<div className="span3 file-tile__thumbnail-container"> <div className="span3 file-tile__thumbnail-container">
<a href="#" onClick={() => navigate(`show=${uri}`)}><Thumbnail className="file-tile__thumbnail" {... metadata && metadata.thumbnail ? {src: metadata.thumbnail} : {}} alt={'Photo for ' + this.props.uri} /></a> <a href="#" onClick={() => navigate(`show=${uri}`)}><Thumbnail className="file-tile__thumbnail" {... metadata && metadata.thumbnail ? {src: metadata.thumbnail} : {}} alt={'Photo for ' + this.props.uri} /></a>
@ -101,7 +91,6 @@ const FileTileStream = React.createClass({
</h3> </h3>
</div> </div>
<div className="card__actions"> <div className="card__actions">
<FileActions uri={this.props.uri} outpoint={this.props.outpoint} metadata={metadata} contentType={this.props.contentType} />
</div> </div>
<div className="card__content"> <div className="card__content">
<p className="file-tile__description"> <p className="file-tile__description">
@ -125,6 +114,6 @@ const FileTileStream = React.createClass({
</section> </section>
); );
} }
}); }
export default FileTileStream export default FileTileStream

View file

@ -54,6 +54,8 @@ export const DOWNLOADING_STARTED = 'DOWNLOADING_STARTED'
export const DOWNLOADING_PROGRESSED = 'DOWNLOADING_PROGRESSED' export const DOWNLOADING_PROGRESSED = 'DOWNLOADING_PROGRESSED'
export const DOWNLOADING_COMPLETED = 'DOWNLOADING_COMPLETED' export const DOWNLOADING_COMPLETED = 'DOWNLOADING_COMPLETED'
export const PLAY_VIDEO_STARTED = 'PLAY_VIDEO_STARTED' export const PLAY_VIDEO_STARTED = 'PLAY_VIDEO_STARTED'
export const FETCH_AVAILABILITY_STARTED = 'FETCH_AVAILABILITY_STARTED'
export const FETCH_AVAILABILITY_COMPLETED = 'FETCH_AVAILABILITY_COMPLETED'
// Search // Search
export const SEARCH_STARTED = 'SEARCH_STARTED' export const SEARCH_STARTED = 'SEARCH_STARTED'

View file

@ -9,7 +9,7 @@ import {
FilePrice, FilePrice,
BusyMessage BusyMessage
} from 'component/common.js'; } from 'component/common.js';
import {FileActions} from 'component/file-actions.js'; import FileActions from 'component/fileActions';
import Link from 'component/link'; import Link from 'component/link';
import UriIndicator from 'component/channel-indicator.js'; import UriIndicator from 'component/channel-indicator.js';

View file

@ -1,4 +1,5 @@
import * as types from 'constants/action_types' import * as types from 'constants/action_types'
import lbry from 'lbry'
const reducers = {} const reducers = {}
const defaultState = { const defaultState = {
@ -9,6 +10,9 @@ const defaultState = {
upgradeSkipped: sessionStorage.getItem('upgradeSkipped'), upgradeSkipped: sessionStorage.getItem('upgradeSkipped'),
daemonReady: false, daemonReady: false,
platform: window.navigator.platform, platform: window.navigator.platform,
obscureNsfw: !lbry.getClientSetting('showNsfw'),
hidePrice: false,
hasSignature: false,
} }
reducers[types.NAVIGATE] = function(state, action) { reducers[types.NAVIGATE] = function(state, action) {

View file

@ -0,0 +1,45 @@
import * as types from 'constants/action_types'
const reducers = {}
const defaultState = {
}
reducers[types.FETCH_AVAILABILITY_STARTED] = function(state, action) {
const {
uri,
} = action.data
const newFetching = Object.assign({}, state.fetching)
const newByUri = Object.assign({}, newFetching.byUri)
newByUri[uri] = true
newFetching.byUri = newByUri
return Object.assign({}, state, {
fetching: newFetching,
})
}
reducers[types.FETCH_AVAILABILITY_COMPLETED] = function(state, action) {
const {
uri,
availability,
} = action.data
const newFetching = Object.assign({}, state.fetching)
const newFetchingByUri = Object.assign({}, newFetching.byUri)
const newAvailabilityByUri = Object.assign({}, state.byUri)
delete newFetchingByUri[uri]
newFetching.byUri = newFetchingByUri
newAvailabilityByUri[uri] = availability
return Object.assign({}, state, {
fetching: newFetching,
byUri: newAvailabilityByUri
})
}
export default function reducer(state = defaultState, action) {
const handler = reducers[action.type];
if (handler) return handler(state, action);
return state;
}

View file

@ -1,4 +1,5 @@
import * as types from 'constants/action_types' import * as types from 'constants/action_types'
import lbryuri from 'lbryuri'
const reducers = {} const reducers = {}
const defaultState = { const defaultState = {

View file

@ -1,4 +1,5 @@
import * as types from 'constants/action_types' import * as types from 'constants/action_types'
import lbryuri from 'lbryuri'
const reducers = {} const reducers = {}
const defaultState = { const defaultState = {
@ -18,10 +19,11 @@ reducers[types.SEARCH_STARTED] = function(state, action) {
reducers[types.SEARCH_COMPLETED] = function(state, action) { reducers[types.SEARCH_COMPLETED] = function(state, action) {
const { const {
query, query,
results,
} = action.data } = action.data
const oldResults = Object.assign({}, state.results) const oldResults = Object.assign({}, state.results)
const newByQuery = Object.assign({}, oldResults.byQuery) const newByQuery = Object.assign({}, oldResults.byQuery)
newByQuery[query] = action.data.results newByQuery[query] = results
const newResults = Object.assign({}, oldResults, { const newResults = Object.assign({}, oldResults, {
byQuery: newByQuery byQuery: newByQuery
}) })

View file

@ -19,7 +19,13 @@ export const selectCurrentPage = createSelector(
export const selectCurrentUri = createSelector( export const selectCurrentUri = createSelector(
selectCurrentPath, selectCurrentPath,
(path) => path.split('://')[1] (path) => {
if (path.match(/=/)) {
return path.split('=')[1]
} else {
return undefined
}
}
) )
export const selectPlatform = createSelector( export const selectPlatform = createSelector(
@ -145,3 +151,18 @@ export const selectDaemonReady = createSelector(
_selectState, _selectState,
(state) => state.daemonReady (state) => state.daemonReady
) )
export const selectObscureNsfw = createSelector(
_selectState,
(state) => !!state.obscureNsfw
)
export const selectHidePrice = createSelector(
_selectState,
(state) => !!state.hidePrice
)
export const selectHasSignature = createSelector(
_selectState,
(state) => !!state.hasSignature
)

View file

@ -0,0 +1,42 @@
import {
createSelector,
} from 'reselect'
const _selectState = state => state.availability
export const selectAvailabilityByUri = createSelector(
_selectState,
(state) => state.byUri || {}
)
export const selectFetchingAvailability = createSelector(
_selectState,
(state) => state.fetching || {}
)
export const selectFetchingAvailabilityByUri = createSelector(
selectFetchingAvailability,
(fetching) => fetching.byUri || {}
)
const selectAvailabilityForUri = (state, props) => {
return selectAvailabilityByUri(state)[props.uri]
}
export const makeSelectAvailabilityForUri = () => {
return createSelector(
selectAvailabilityForUri,
(availability) => availability
)
}
const selectFetchingAvailabilityForUri = (state, props) => {
return selectFetchingAvailabilityByUri(state)[props.uri]
}
export const makeSelectFetchingAvailabilityForUri = () => {
return createSelector(
selectFetchingAvailabilityForUri,
(fetching) => fetching
)
}

View file

@ -1,6 +1,7 @@
import { import {
createSelector, createSelector,
} from 'reselect' } from 'reselect'
import lbryuri from 'lbryuri'
import { import {
selectCurrentUri, selectCurrentUri,
} from 'selectors/app' } from 'selectors/app'
@ -22,3 +23,43 @@ export const selectCurrentUriClaimOutpoint = createSelector(
selectCurrentUriClaim, selectCurrentUriClaim,
(claim) => `${claim.txid}:${claim.nout}` (claim) => `${claim.txid}:${claim.nout}`
) )
const selectClaimForUri = (state, props) => {
const uri = lbryuri.normalize(props.uri)
return selectClaimsByUri(state)[uri]
}
export const makeSelectClaimForUri = () => {
return createSelector(
selectClaimForUri,
(claim) => claim
)
}
const selectMetadataForUri = (state, props) => {
const claim = selectClaimForUri(state, props)
const metadata = claim && claim.value && claim.value.stream && claim.value.stream.metadata
return metadata ? metadata : undefined
}
export const makeSelectMetadataForUri = () => {
return createSelector(
selectMetadataForUri,
(metadata) => metadata
)
}
const selectSourceForUri = (state, props) => {
const claim = selectClaimForUri(state, props)
const source = claim && claim.value && claim.value.stream && claim.value.stream.source
return source ? source : undefined
}
export const makeSelectSourceForUri = () => {
return createSelector(
selectSourceForUri,
(source) => source
)
}

View file

@ -72,3 +72,13 @@ export const shouldFetchCurrentUriFileInfo = createSelector(
} }
) )
const selectFileInfoForUri = (state, props) => {
return selectAllFileInfoByUri(state)[props.uri]
}
export const makeSelectFileInfoForUri = () => {
return createSelector(
selectFileInfoForUri,
(fileInfo) => fileInfo
)
}

View file

@ -6,6 +6,7 @@ import {
createLogger createLogger
} from 'redux-logger' } from 'redux-logger'
import appReducer from 'reducers/app'; import appReducer from 'reducers/app';
import availabilityReducer from 'reducers/availability'
import certificatesReducer from 'reducers/certificates' import certificatesReducer from 'reducers/certificates'
import claimsReducer from 'reducers/claims' import claimsReducer from 'reducers/claims'
import contentReducer from 'reducers/content'; import contentReducer from 'reducers/content';
@ -47,6 +48,7 @@ function enableBatching(reducer) {
const reducers = redux.combineReducers({ const reducers = redux.combineReducers({
app: appReducer, app: appReducer,
availability: availabilityReducer,
certificates: certificatesReducer, certificates: certificatesReducer,
claims: claimsReducer, claims: claimsReducer,
fileInfo: fileInfoReducer, fileInfo: fileInfoReducer,