mirror of
https://github.com/LBRYFoundation/lbry-desktop.git
synced 2025-08-27 07:23:31 +00:00
A bunch of improvements and broken the back of the file rendering code now
This commit is contained in:
parent
a77370afc9
commit
e88f06c17c
23 changed files with 385 additions and 118 deletions
21
ui/js/actions/availability.js
Normal file
21
ui/js/actions/availability.js
Normal 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,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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({
|
||||||
|
|
21
ui/js/component/fileActions/index.js
Normal file
21
ui/js/component/fileActions/index.js
Normal 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)
|
|
@ -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
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
componentDidMount() {
|
||||||
obscureNsfw: !lbry.getClientSetting('showNsfw'),
|
|
||||||
hidePrice: false,
|
|
||||||
hasSignature: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
componentDidMount: function() {
|
|
||||||
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
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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} />
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,9 @@ class FileTile extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
return displayStyle == 'card' ?
|
return displayStyle == 'card' ?
|
||||||
<FileCardStream uri={uri} />
|
<FileCardStream uri={uri} />
|
||||||
:
|
:
|
||||||
<FileTileStream uri={uri} key={uri} />
|
<FileTileStream uri={uri} key={uri} />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
componentDidMount() {
|
||||||
obscureNsfw: !lbry.getClientSetting('showNsfw'),
|
|
||||||
hidePrice: false,
|
|
||||||
hasSignature: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
componentDidMount: function() {
|
|
||||||
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
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
45
ui/js/reducers/availability.js
Normal file
45
ui/js/reducers/availability.js
Normal 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;
|
||||||
|
}
|
|
@ -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 = {
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
||||||
|
|
42
ui/js/selectors/availability.js
Normal file
42
ui/js/selectors/availability.js
Normal 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
|
||||||
|
)
|
||||||
|
}
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Reference in a new issue