commit
c0053363ff
28 changed files with 287 additions and 194 deletions
|
@ -15,23 +15,43 @@ const app = require('electron').remote.app;
|
|||
const {download} = remote.require('electron-dl');
|
||||
const fs = remote.require('fs');
|
||||
|
||||
export function doNavigate(path) {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState()
|
||||
const previousPath = selectCurrentPath(state)
|
||||
const previousTitle = selectPageTitle(state)
|
||||
history.pushState(state, previousTitle, previousPath);
|
||||
const queryStringFromParams = (params) => {
|
||||
return Object
|
||||
.keys(params)
|
||||
.map(key => `${key}=${params[key]}`)
|
||||
.join('&')
|
||||
}
|
||||
|
||||
export function doNavigate(path, params = {}) {
|
||||
return function(dispatch, getState) {
|
||||
let url = path
|
||||
if (params)
|
||||
url = `${url}?${queryStringFromParams(params)}`
|
||||
|
||||
dispatch(doChangePath(url))
|
||||
|
||||
const state = getState()
|
||||
const pageTitle = selectPageTitle(state)
|
||||
history.pushState(params, pageTitle, url)
|
||||
window.document.title = pageTitle
|
||||
}
|
||||
}
|
||||
|
||||
export function doChangePath(path) {
|
||||
return function(dispatch, getState) {
|
||||
dispatch({
|
||||
type: types.NAVIGATE,
|
||||
type: types.CHANGE_PATH,
|
||||
data: {
|
||||
path,
|
||||
}
|
||||
})
|
||||
|
||||
const pageTitle = selectPageTitle(state)
|
||||
}
|
||||
}
|
||||
|
||||
window.document.title = pageTitle
|
||||
export function doHistoryBack() {
|
||||
return function(dispatch, getState) {
|
||||
history.back()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,16 +73,6 @@ export function doCloseModal() {
|
|||
}
|
||||
}
|
||||
|
||||
export function doHistoryBack() {
|
||||
return function(dispatch, getState) {
|
||||
if (window.history.length > 1) {
|
||||
window.history.back();
|
||||
} else {
|
||||
dispatch(doNavigate('discover'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function doUpdateDownloadProgress(percent) {
|
||||
return {
|
||||
type: types.UPGRADE_DOWNLOAD_PROGRESSED,
|
||||
|
|
|
@ -3,9 +3,6 @@ import lbry from 'lbry'
|
|||
import lbryio from 'lbryio'
|
||||
import lbryuri from 'lbryuri'
|
||||
import lighthouse from 'lighthouse'
|
||||
import {
|
||||
selectSearchQuery,
|
||||
} from 'selectors/search'
|
||||
import {
|
||||
doResolveUri,
|
||||
} from 'actions/content'
|
||||
|
@ -14,6 +11,7 @@ import {
|
|||
} from 'actions/app'
|
||||
import {
|
||||
selectCurrentPage,
|
||||
selectSearchQuery,
|
||||
} from 'selectors/app'
|
||||
|
||||
export function doSearchContent(query) {
|
||||
|
@ -33,7 +31,9 @@ export function doSearchContent(query) {
|
|||
data: { query }
|
||||
})
|
||||
|
||||
if(page != 'discover' && query != undefined) dispatch(doNavigate('discover'))
|
||||
if(page != 'search' && query != undefined) {
|
||||
dispatch(doNavigate('search', { query: query }))
|
||||
}
|
||||
|
||||
lighthouse.search(query).then(results => {
|
||||
results.forEach(result => {
|
||||
|
@ -75,3 +75,49 @@ export function doDeactivateSearch() {
|
|||
type: types.DEACTIVATE_SEARCH,
|
||||
}
|
||||
}
|
||||
|
||||
export function doSetSearchQuery(query) {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState()
|
||||
|
||||
dispatch(doNavigate('/search', { query }))
|
||||
}
|
||||
}
|
||||
|
||||
export function doSearch() {
|
||||
return function(dispatch, getState) {
|
||||
const state = getState()
|
||||
const page = selectCurrentPage(state)
|
||||
const query = selectSearchQuery(state)
|
||||
|
||||
if (!query) {
|
||||
return dispatch({
|
||||
type: types.SEARCH_CANCELLED,
|
||||
})
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: types.SEARCH_STARTED,
|
||||
data: { query }
|
||||
})
|
||||
|
||||
lighthouse.search(query).then(results => {
|
||||
results.forEach(result => {
|
||||
const uri = lbryuri.build({
|
||||
channelName: result.channel_name,
|
||||
contentName: result.name,
|
||||
claimId: result.channel_id || result.claim_id,
|
||||
})
|
||||
dispatch(doResolveUri(uri))
|
||||
})
|
||||
|
||||
dispatch({
|
||||
type: types.SEARCH_COMPLETED,
|
||||
data: {
|
||||
query,
|
||||
results,
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ export function doGetNewAddress() {
|
|||
type: types.GET_NEW_ADDRESS_STARTED
|
||||
})
|
||||
|
||||
console.log('do get new address');
|
||||
lbry.wallet_new_address().then(function(address) {
|
||||
localStorage.setItem('wallet_address', address);
|
||||
dispatch({
|
||||
|
|
|
@ -44,7 +44,7 @@ const makeSelect = () => {
|
|||
}
|
||||
|
||||
const perform = (dispatch) => ({
|
||||
navigate: (path) => dispatch(doNavigate(path)),
|
||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
||||
})
|
||||
|
||||
export default connect(makeSelect, perform)(FileCardStream)
|
||||
|
|
|
@ -67,7 +67,7 @@ class FileCardStream extends React.Component {
|
|||
const isConfirmed = !!metadata;
|
||||
const title = isConfirmed ? metadata.title : uri;
|
||||
const obscureNsfw = this.props.obscureNsfw && isConfirmed && metadata.nsfw;
|
||||
const primaryUrl = 'show=' + uri;
|
||||
const primaryUrl = '/show?uri=' + uri;
|
||||
let description = ""
|
||||
if (isConfirmed) {
|
||||
description = metadata.description
|
||||
|
@ -80,7 +80,7 @@ class FileCardStream extends React.Component {
|
|||
return (
|
||||
<section className={ 'card card--small card--link ' + (obscureNsfw ? 'card--obscured ' : '') } onMouseEnter={this.handleMouseOver.bind(this)} onMouseLeave={this.handleMouseOut.bind(this)}>
|
||||
<div className="card__inner">
|
||||
<a href="#" onClick={() => navigate(primaryUrl)} className="card__link">
|
||||
<Link onClick={() => navigate('/show', { uri })} className="card__link">
|
||||
<div className="card__title-identity">
|
||||
<h5 title={title}><TruncatedText lines={1}>{title}</TruncatedText></h5>
|
||||
<div className="card__subtitle">
|
||||
|
@ -94,12 +94,12 @@ class FileCardStream extends React.Component {
|
|||
<div className="card__content card__subtext card__subtext--two-lines">
|
||||
<TruncatedText lines={2}>{description}</TruncatedText>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
{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" />.
|
||||
To view adult content, please change your <Link className="button-text" onClick={() => navigate('settings')} label="Settings" />.
|
||||
</p>
|
||||
</div>
|
||||
: null}
|
||||
|
|
|
@ -49,7 +49,7 @@ const makeSelect = () => {
|
|||
}
|
||||
|
||||
const perform = (dispatch) => ({
|
||||
navigate: (path) => dispatch(doNavigate(path))
|
||||
navigate: (path, params) => dispatch(doNavigate(path, params))
|
||||
})
|
||||
|
||||
export default connect(makeSelect, perform)(FileTileStream)
|
||||
|
|
|
@ -83,49 +83,81 @@ class FileTileStream extends React.Component {
|
|||
}
|
||||
|
||||
return (
|
||||
<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="span3 file-tile__thumbnail-container">
|
||||
<a href="#" onClick={() => navigate(`show=${uri}`)}>
|
||||
{metadata && metadata.thumbnail ?
|
||||
<Thumbnail key={this.props.uri} className="file-tile__thumbnail" src={metadata.thumbnail} alt={'Photo for ' + this.props.uri} />
|
||||
:
|
||||
<Thumbnail className="file-tile__thumbnail" alt={'Photo for ' + this.props.uri} />
|
||||
}
|
||||
</a>
|
||||
</div>
|
||||
<div className="span9">
|
||||
<div className="card__title-primary">
|
||||
{ !this.props.hidePrice
|
||||
? <FilePrice uri={this.props.uri} />
|
||||
: null}
|
||||
<div className="meta"><a href="#" onClick={() => navigate(`show=${uri}`)}>{uri}</a></div>
|
||||
<h3>
|
||||
<a href="#" onClick={() => navigate(`show=${uri}`)} title={title}>
|
||||
<TruncatedText lines={1}>
|
||||
{title}
|
||||
</TruncatedText>
|
||||
</a>
|
||||
</h3>
|
||||
<section className={ 'card card--small card--link ' + (obscureNsfw ? 'card--obscured ' : '') } onMouseEnter={this.handleMouseOver.bind(this)} onMouseLeave={this.handleMouseOut.bind(this)}>
|
||||
<div className="card__inner">
|
||||
<Link onClick={() => navigate('/show', { uri })} 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={uri} /></span> : null}
|
||||
<UriIndicator uri={uri} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="card__actions">
|
||||
{ metadata && metadata.thumbnail ?
|
||||
<div className="card__media" style={{ backgroundImage: "url('" + metadata.thumbnail + "')" }}></div> :
|
||||
<div className="card__media" style={{ backgroundImage: "url('" + lbry.imagePath('default-thumb.svg') + "')" }}></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>
|
||||
<div className="card__content">
|
||||
<p className="file-tile__description">
|
||||
<TruncatedText lines={2}>{description}</TruncatedText>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
{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" onClick={() => navigate('/settings')} label="Settings" />.
|
||||
</p>
|
||||
</div>
|
||||
: null}
|
||||
</div>
|
||||
{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="#" onClick={() => navigate('settings')} label="Settings" />.
|
||||
</p>
|
||||
</div>
|
||||
: null}
|
||||
</section>
|
||||
// <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="span3 file-tile__thumbnail-container">
|
||||
// <Link onClick={() => navigate('/show', { uri })}>
|
||||
// {metadata && metadata.thumbnail ?
|
||||
// <Thumbnail key={this.props.uri} className="file-tile__thumbnail" src={metadata.thumbnail} alt={'Photo for ' + this.props.uri} />
|
||||
// :
|
||||
// <Thumbnail className="file-tile__thumbnail" alt={'Photo for ' + this.props.uri} />
|
||||
// }
|
||||
// </Link>
|
||||
// </div>
|
||||
// <div className="span9">
|
||||
// <div className="card__title-primary">
|
||||
// { !this.props.hidePrice
|
||||
// ? <FilePrice uri={this.props.uri} />
|
||||
// : null}
|
||||
// <div className="meta"><Link onClick={() => navigate('/show', { uri })}>{uri}</Link></div>
|
||||
// <h3>
|
||||
// <Link onClick={() => navigate('/show', { uri })} title={title}>
|
||||
// <TruncatedText lines={1}>
|
||||
// {title}
|
||||
// </TruncatedText>
|
||||
// </Link>
|
||||
// </h3>
|
||||
// </div>
|
||||
// <div className="card__actions">
|
||||
// </div>
|
||||
// <div className="card__content">
|
||||
// <p className="file-tile__description">
|
||||
// <TruncatedText lines={2}>{description}</TruncatedText>
|
||||
// </p>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// {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" onClick={() => navigate('/settings')} label="Settings" />.
|
||||
// </p>
|
||||
// </div>
|
||||
// : null}
|
||||
// </section>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,22 +14,22 @@ export const Header = (props) => {
|
|||
<Link onClick={back} button="alt button--flat" icon="icon-arrow-left" />
|
||||
</div>
|
||||
<div className="header__item">
|
||||
<Link onClick={() => navigate('discover')} button="alt button--flat" icon="icon-home" />
|
||||
<Link onClick={() => navigate('/discover')} button="alt button--flat" icon="icon-home" />
|
||||
</div>
|
||||
<div className="header__item header__item--wunderbar">
|
||||
<WunderBar/>
|
||||
</div>
|
||||
<div className="header__item">
|
||||
<Link onClick={() => navigate('wallet')} button="text" icon="icon-bank" label={balance} ></Link>
|
||||
<Link onClick={() => navigate('/wallet')} button="text" icon="icon-bank" label={balance} ></Link>
|
||||
</div>
|
||||
<div className="header__item">
|
||||
<Link onClick={() => navigate('publish')} button="primary button--flat" icon="icon-upload" label="Publish" />
|
||||
<Link onClick={() => navigate('/publish')} button="primary button--flat" icon="icon-upload" label="Publish" />
|
||||
</div>
|
||||
<div className="header__item">
|
||||
<Link onClick={() => navigate('downloaded')} button="alt button--flat" icon="icon-folder" />
|
||||
<Link onClick={() => navigate('/downloaded')} button="alt button--flat" icon="icon-folder" />
|
||||
</div>
|
||||
<div className="header__item">
|
||||
<Link onClick={() => navigate('settings')} button="alt button--flat" icon="icon-gear" />
|
||||
<Link onClick={() => navigate('/settings')} button="alt button--flat" icon="icon-gear" />
|
||||
</div>
|
||||
</header>
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react'
|
||||
import Link from 'component/link'
|
||||
|
||||
const SubHeader = (props) => {
|
||||
const {
|
||||
|
@ -12,9 +13,9 @@ const SubHeader = (props) => {
|
|||
|
||||
for(let link of Object.keys(subLinks)) {
|
||||
links.push(
|
||||
<a href="#" onClick={() => navigate(link)} key={link} className={link == currentPage ? 'sub-header-selected' : 'sub-header-unselected' }>
|
||||
<Link onClick={(event) => navigate(`/${link}`, event)} key={link} className={link == currentPage ? 'sub-header-selected' : 'sub-header-unselected' }>
|
||||
{subLinks[link]}
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -23,10 +23,12 @@ const select = (state) => ({
|
|||
|
||||
const perform = (dispatch) => ({
|
||||
// navigate: (path) => dispatch(doNavigate(path)),
|
||||
onSearch: (query) => dispatch(doSearchContent(query)),
|
||||
onSubmit: (query) => dispatch(doSearchContent(query)),
|
||||
activateSearch: () => dispatch(doActivateSearch()),
|
||||
deactivateSearch: () => setTimeout(() => { dispatch(doDeactivateSearch()) }, 50),
|
||||
// onSearch: (query) => dispatch(doSearchContent(query)),
|
||||
// onSubmit: (query) => dispatch(doSearchContent(query)),
|
||||
// activateSearch: () => dispatch(doActivateSearch()),
|
||||
// deactivateSearch: () => setTimeout(() => { dispatch(doDeactivateSearch()) }, 50),
|
||||
onSearch: (query) => dispatch(doNavigate('/search', { query })),
|
||||
onSubmit: (query) => console.debug('you submitted'),
|
||||
})
|
||||
|
||||
export default connect(select, perform)(Wunderbar)
|
||||
|
|
|
@ -61,8 +61,6 @@ class WunderBar extends React.PureComponent {
|
|||
isActive: true
|
||||
}
|
||||
|
||||
this.props.activateSearch()
|
||||
|
||||
this._focusPending = true;
|
||||
//below is hacking, improved when we have proper routing
|
||||
if (!this.state.address.startsWith('lbry://') && this.state.icon !== "icon-search") //onFocus, if they are not on an exact URL or a search page, clear the bar
|
||||
|
@ -73,7 +71,6 @@ class WunderBar extends React.PureComponent {
|
|||
}
|
||||
|
||||
onBlur() {
|
||||
this.props.deactivateSearch()
|
||||
let commonState = {isActive: false};
|
||||
if (this._resetOnNextBlur) {
|
||||
this.setState(Object.assign({}, this._stateBeforeSearch, commonState));
|
||||
|
@ -123,7 +120,7 @@ class WunderBar extends React.PureComponent {
|
|||
return (
|
||||
<div className={'wunderbar' + (this.state.isActive ? ' wunderbar--active' : '')}>
|
||||
{this.state.icon ? <Icon fixed icon={this.state.icon} /> : '' }
|
||||
<input className="wunderbar__input" type="search" placeholder="Type a LBRY address or search term"
|
||||
<input className="wunderbar__input" type="search"
|
||||
ref={this.onReceiveRef}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export const NAVIGATE = 'NAVIGATE'
|
||||
export const CHANGE_PATH = 'CHANGE_PATH'
|
||||
export const OPEN_MODAL = 'OPEN_MODAL'
|
||||
export const CLOSE_MODAL = 'CLOSE_MODAL'
|
||||
export const HISTORY_BACK = 'HISTORY_BACK'
|
||||
|
|
|
@ -11,8 +11,10 @@ import { Provider } from 'react-redux';
|
|||
import store from 'store.js';
|
||||
import { runTriggers } from 'triggers'
|
||||
import {
|
||||
doDaemonReady
|
||||
doDaemonReady,
|
||||
doChangePath,
|
||||
} from 'actions/app'
|
||||
import parseQueryParams from 'util/query_params'
|
||||
|
||||
const {remote} = require('electron');
|
||||
const contextMenu = remote.require('./menu/context-menu');
|
||||
|
@ -26,6 +28,14 @@ window.addEventListener('contextmenu', (event) => {
|
|||
event.preventDefault();
|
||||
});
|
||||
|
||||
window.addEventListener('popstate', (event) => {
|
||||
const pathname = document.location.pathname
|
||||
const queryString = document.location.search
|
||||
if (pathname.match(/dist/)) return
|
||||
|
||||
app.store.dispatch(doChangePath(`${pathname}${queryString}`))
|
||||
})
|
||||
|
||||
const initialState = app.store.getState();
|
||||
app.store.subscribe(runTriggers);
|
||||
runTriggers();
|
||||
|
@ -41,6 +51,7 @@ var init = function() {
|
|||
|
||||
function onDaemonReady() {
|
||||
app.store.dispatch(doDaemonReady())
|
||||
window.history.pushState({}, "Discover", '/discover');
|
||||
ReactDOM.render(<Provider store={store}><div>{ lbryio.enabled ? <AuthOverlay/> : '' }<App /><SnackBar /></div></Provider>, canvas)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,21 +3,14 @@ import {
|
|||
connect
|
||||
} from 'react-redux'
|
||||
import {
|
||||
selectFeaturedUris
|
||||
selectFeaturedUris,
|
||||
selectFetchingFeaturedUris,
|
||||
} from 'selectors/content'
|
||||
import {
|
||||
doSearchContent,
|
||||
} from 'actions/search'
|
||||
import {
|
||||
selectIsSearching,
|
||||
selectSearchQuery,
|
||||
selectCurrentSearchResults,
|
||||
selectSearchActivated,
|
||||
} from 'selectors/search'
|
||||
import DiscoverPage from './view'
|
||||
|
||||
const select = (state) => ({
|
||||
featuredUris: selectFeaturedUris(state),
|
||||
fetchingFeaturedUris: selectFetchingFeaturedUris(state),
|
||||
})
|
||||
|
||||
const perform = (dispatch) => ({
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import lbryio from 'lbryio.js';
|
||||
import lbryuri from 'lbryuri'
|
||||
import FileTile from 'component/fileTile';
|
||||
import { FileTileStream } from 'component/fileTileStream'
|
||||
import {ToolTip} from 'component/tooltip.js';
|
||||
|
@ -24,80 +25,26 @@ const FeaturedCategory = (props) => {
|
|||
|
||||
const DiscoverPage = (props) => {
|
||||
const {
|
||||
featuredUris
|
||||
featuredUris,
|
||||
fetchingFeaturedUris,
|
||||
} = props
|
||||
const failed = Object.keys(featuredUris).length === 0
|
||||
|
||||
return <main>{
|
||||
Object.keys(featuredUris).length === 0 ?
|
||||
<div className="empty">Failed to load landing content.</div> :
|
||||
<div>
|
||||
{
|
||||
Object.keys(featuredUris).map((category) => {
|
||||
return featuredUris[category].length ?
|
||||
<FeaturedCategory key={category} category={category} names={featuredUris[category]} /> :
|
||||
'';
|
||||
})
|
||||
}
|
||||
</div>
|
||||
}</main>
|
||||
let content
|
||||
|
||||
if (fetchingFeaturedUris) content = <div className="empty">Fetching landing content.</div>
|
||||
if (!fetchingFeaturedUris && failed) content = <div className="empty">Failed to load landing content.</div>
|
||||
if (!fetchingFeaturedUris && !failed) {
|
||||
content = Object.keys(featuredUris).map(category => {
|
||||
return featuredUris[category].length ?
|
||||
<FeaturedCategory key={category} category={category} names={featuredUris[category]} /> :
|
||||
'';
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<main>{content}</main>
|
||||
)
|
||||
}
|
||||
|
||||
//
|
||||
// let DiscoverPage = React.createClass({
|
||||
// getInitialState: function() {
|
||||
// return {
|
||||
// featuredUris: {},
|
||||
// failed: false
|
||||
// };
|
||||
// },
|
||||
// componentWillMount: function() {
|
||||
// lbryio.call('discover', 'list', { version: "early-access" } ).then(({Categories, Uris}) => {
|
||||
// let featuredUris = {}
|
||||
// Categories.forEach((category) => {
|
||||
// if (Uris[category] && Uris[category].length) {
|
||||
// featuredUris[category] = Uris[category]
|
||||
// }
|
||||
// })
|
||||
// this.setState({ featuredUris: featuredUris });
|
||||
// }, () => {
|
||||
// this.setState({
|
||||
// failed: true
|
||||
// })
|
||||
// });
|
||||
// },
|
||||
// render: function() {
|
||||
// return <main>{
|
||||
// this.state.failed ?
|
||||
// <div className="empty">Failed to load landing content.</div> :
|
||||
// <div>
|
||||
// {
|
||||
// Object.keys(this.state.featuredUris).map((category) => {
|
||||
// return this.state.featuredUris[category].length ?
|
||||
// <FeaturedCategory key={category} category={category} names={this.state.featuredUris[category]} /> :
|
||||
// '';
|
||||
// })
|
||||
// }
|
||||
// </div>
|
||||
// }</main>;
|
||||
// }
|
||||
// })
|
||||
|
||||
// const DiscoverPage = (props) => {
|
||||
// const {
|
||||
// isSearching,
|
||||
// query,
|
||||
// results,
|
||||
// searchActive,
|
||||
// } = props
|
||||
//
|
||||
// return (
|
||||
// <main>
|
||||
// { (!searchActive || (!isSearching && !query)) && <FeaturedContent {...props} /> }
|
||||
// { searchActive && isSearching ? <SearchActive /> : null }
|
||||
// { searchActive && !isSearching && query && results.length ? <SearchResults results={results} /> : null }
|
||||
// { searchActive && !isSearching && query && !results.length ? <SearchNoResults query={query} /> : null }
|
||||
// </main>
|
||||
// );
|
||||
// }
|
||||
|
||||
export default DiscoverPage;
|
|
@ -22,7 +22,7 @@ class FileListDownloaded extends React.Component {
|
|||
if (fetching) {
|
||||
content = <BusyMessage message="Loading" />
|
||||
} else if (!downloadedContent.length) {
|
||||
content = <span>You haven't downloaded anything from LBRY yet. Go <Link href="#" onClick={() => navigate('discover')} label="search for your first download" />!</span>
|
||||
content = <span>You haven't downloaded anything from LBRY yet. Go <Link onClick={() => navigate('/discover')} label="search for your first download" />!</span>
|
||||
} else {
|
||||
content = <FileList fileInfos={downloadedContent} hidePrices={true} />
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ class FileListPublished extends React.Component {
|
|||
if (fetching) {
|
||||
content = <BusyMessage message="Loading" />
|
||||
} else if (!publishedContent.length) {
|
||||
content = <span>You haven't downloaded anything from LBRY yet. Go <Link href="#" onClick={() => navigate('discover')} label="search for your first download" />!</span>
|
||||
content = <span>You haven't downloaded anything from LBRY yet. Go <Link onClick={() => navigate('/discover')} label="search for your first download" />!</span>
|
||||
} else {
|
||||
content = <FileList fileInfos={publishedContent} hidePrices={true} />
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ var HelpPage = React.createClass({
|
|||
<div className="card__title-primary"><h3>Report a Bug</h3></div>
|
||||
<div className="card__content">
|
||||
<p>Did you find something wrong?</p>
|
||||
<p><Link href="?report" label="Submit a Bug Report" icon="icon-bug" button="alt" /></p>
|
||||
<p><Link onClick={() => navigate('report')} label="Submit a Bug Report" icon="icon-bug" button="alt" /></p>
|
||||
<div className="meta">Thanks! LBRY is made by its users.</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
@ -147,7 +147,7 @@ var PublishPage = React.createClass({
|
|||
});
|
||||
},
|
||||
handlePublishStartedConfirmed: function() {
|
||||
this.props.navigate('published')
|
||||
this.props.navigate('/published')
|
||||
},
|
||||
handlePublishError: function(error) {
|
||||
this.setState({
|
||||
|
|
|
@ -7,10 +7,12 @@ import {
|
|||
} from 'actions/search'
|
||||
import {
|
||||
selectIsSearching,
|
||||
selectSearchQuery,
|
||||
selectCurrentSearchResults,
|
||||
selectSearchActivated,
|
||||
} from 'selectors/search'
|
||||
import {
|
||||
selectSearchQuery,
|
||||
} from 'selectors/app'
|
||||
import {
|
||||
doNavigate,
|
||||
} from 'actions/app'
|
||||
|
|
|
@ -18,7 +18,7 @@ const SearchNoResults = (props) => {
|
|||
return <section>
|
||||
<span className="empty">
|
||||
No one has checked anything in for {query} yet.
|
||||
<Link label="Be the first" href="#" onClick={() => navigate('publish')} />
|
||||
<Link label="Be the first" onClick={() => navigate('/publish')} />
|
||||
</span>
|
||||
</section>;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ const ShowPage = (props) => {
|
|||
</div>
|
||||
<div className="card__content">
|
||||
{ uriLookupComplete ?
|
||||
<p>This location is not yet in use. { ' ' }<Link href="#" onClick={() => navigate('publish')} label="Put something here" />.</p> :
|
||||
<p>This location is not yet in use. { ' ' }<Link onClick={() => navigate('/publish')} label="Put something here" />.</p> :
|
||||
<BusyMessage message="Loading magic decentralized data..." />
|
||||
}
|
||||
</div>
|
||||
|
|
|
@ -19,7 +19,7 @@ reducers[types.DAEMON_READY] = function(state, action) {
|
|||
})
|
||||
}
|
||||
|
||||
reducers[types.NAVIGATE] = function(state, action) {
|
||||
reducers[types.CHANGE_PATH] = function(state, action) {
|
||||
return Object.assign({}, state, {
|
||||
currentPath: action.data.path,
|
||||
})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as types from 'constants/action_types'
|
||||
|
||||
const reducers = {}
|
||||
const address = sessionStorage.getItem('receiveAddress')
|
||||
const address = localStorage.getItem('receiveAddress')
|
||||
const buildDraftTransaction = () => ({
|
||||
amount: undefined,
|
||||
address: undefined
|
||||
|
@ -50,7 +50,7 @@ reducers[types.GET_NEW_ADDRESS_STARTED] = function(state, action) {
|
|||
reducers[types.GET_NEW_ADDRESS_COMPLETED] = function(state, action) {
|
||||
const { address } = action.data
|
||||
|
||||
sessionStorage.setItem('receiveAddress', address)
|
||||
localStorage.setItem('receiveAddress', address)
|
||||
return Object.assign({}, state, {
|
||||
gettingNewAddress: false,
|
||||
receiveAddress: address
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import {createSelector} from 'reselect'
|
||||
import {
|
||||
selectIsSearching,
|
||||
selectSearchActivated,
|
||||
} from 'selectors/search'
|
||||
import parseQueryParams from 'util/query_params'
|
||||
import lbryuri from 'lbryuri'
|
||||
|
||||
export const _selectState = state => state.app || {}
|
||||
|
||||
|
@ -18,14 +16,26 @@ export const selectCurrentPath = createSelector(
|
|||
|
||||
export const selectCurrentPage = createSelector(
|
||||
selectCurrentPath,
|
||||
selectSearchActivated,
|
||||
(path, searchActivated) => {
|
||||
if (searchActivated) return 'search'
|
||||
|
||||
return path.split('=')[0]
|
||||
(path) => {
|
||||
return path.replace(/^\//, '').split('?')[0]
|
||||
}
|
||||
)
|
||||
|
||||
export const selectCurrentParams = createSelector(
|
||||
selectCurrentPath,
|
||||
(path) => {
|
||||
if (path === undefined) return {}
|
||||
if (!path.match(/\?/)) return {}
|
||||
|
||||
return parseQueryParams(path.split('?')[1])
|
||||
}
|
||||
)
|
||||
|
||||
export const selectSearchQuery = createSelector(
|
||||
selectCurrentParams,
|
||||
(params) => params.query
|
||||
)
|
||||
|
||||
export const selectCurrentUri = createSelector(
|
||||
selectCurrentPath,
|
||||
(path) => {
|
||||
|
@ -62,7 +72,7 @@ export const selectPageTitle = createSelector(
|
|||
case 'rewards':
|
||||
return page.charAt(0).toUpperCase() + page.slice(1)
|
||||
case 'show':
|
||||
return lbryuri.normalize(page)
|
||||
return lbryuri.normalize(uri)
|
||||
case 'downloaded':
|
||||
return 'Downloads & Purchases'
|
||||
case 'published':
|
||||
|
@ -85,7 +95,8 @@ export const selectPageTitle = createSelector(
|
|||
|
||||
export const selectWunderBarAddress = createSelector(
|
||||
selectPageTitle,
|
||||
(title) => title
|
||||
selectSearchQuery,
|
||||
(title, query) => query || title
|
||||
)
|
||||
|
||||
export const selectWunderBarIcon = createSelector(
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { createSelector } from 'reselect'
|
||||
import {
|
||||
selectCurrentParams,
|
||||
selectDaemonReady,
|
||||
selectSearchQuery,
|
||||
} from 'selectors/app'
|
||||
|
||||
export const _selectState = state => state.search || {}
|
||||
|
||||
export const selectSearchQuery = createSelector(
|
||||
_selectState,
|
||||
(state) => state.query
|
||||
)
|
||||
|
||||
export const selectIsSearching = createSelector(
|
||||
_selectState,
|
||||
(state) => !!state.searching
|
||||
|
@ -32,3 +32,18 @@ export const selectSearchActivated = createSelector(
|
|||
_selectState,
|
||||
(state) => !!state.activated
|
||||
)
|
||||
|
||||
export const shouldSearch = createSelector(
|
||||
selectDaemonReady,
|
||||
selectSearchQuery,
|
||||
selectIsSearching,
|
||||
selectSearchResultsByQuery,
|
||||
(daemonReady, query, isSearching, resultsByQuery) => {
|
||||
if (!daemonReady) return false
|
||||
if (!query) return false
|
||||
if (isSearching) return false
|
||||
if (Object.keys(resultsByQuery).indexOf(query) != -1) return false
|
||||
|
||||
return true
|
||||
}
|
||||
)
|
||||
|
|
|
@ -34,6 +34,12 @@ import {
|
|||
import {
|
||||
doFetchCurrentUriAvailability,
|
||||
} from 'actions/availability'
|
||||
import {
|
||||
shouldSearch,
|
||||
} from 'selectors/search'
|
||||
import {
|
||||
doSearch,
|
||||
} from 'actions/search'
|
||||
|
||||
const triggers = []
|
||||
|
||||
|
@ -77,6 +83,11 @@ triggers.push({
|
|||
action: doFetchCurrentUriAvailability,
|
||||
})
|
||||
|
||||
triggers.push({
|
||||
selector: shouldSearch,
|
||||
action: doSearch,
|
||||
})
|
||||
|
||||
const runTriggers = function() {
|
||||
triggers.forEach(function(trigger) {
|
||||
const state = app.store.getState();
|
||||
|
|
16
ui/js/util/query_params.js
Normal file
16
ui/js/util/query_params.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
function parseQueryParams(queryString) {
|
||||
if (queryString === '') return {};
|
||||
const parts = queryString
|
||||
.split('?')
|
||||
.pop()
|
||||
.split('&')
|
||||
.map(function(p) { return p.split('=') })
|
||||
|
||||
const params = {};
|
||||
parts.forEach(function(arr) {
|
||||
params[arr[0]] = arr[1];
|
||||
})
|
||||
return params;
|
||||
}
|
||||
|
||||
export default parseQueryParams
|
Loading…
Add table
Reference in a new issue