where's the triggers?! also very broken

This commit is contained in:
Jeremy Kauffman 2017-05-10 20:59:47 -04:00
parent d517316554
commit 3c325b2f0a
40 changed files with 502 additions and 815 deletions

View file

@ -28,7 +28,6 @@ export function doNavigate(path, params = {}) {
if (params) if (params)
url = `${url}?${queryStringFromParams(params)}` url = `${url}?${queryStringFromParams(params)}`
console.log('Path: ' + url);
dispatch(doChangePath(url)) dispatch(doChangePath(url))
const state = getState() const state = getState()
@ -201,19 +200,6 @@ export function doAlertError(errorList) {
} }
} }
export function doSearch(term) {
return function(dispatch, getState) {
const state = getState()
dispatch({
type: types.START_SEARCH,
data: {
searchTerm: term
}
})
}
}
export function doDaemonReady() { export function doDaemonReady() {
return { return {
type: types.DAEMON_READY type: types.DAEMON_READY

View file

@ -40,7 +40,7 @@ export function doResolveUri(uri) {
data: { uri } data: { uri }
}) })
lbry.resolve({ uri }).then((resolutionInfo) => { return lbry.resolve({ uri }).then((resolutionInfo) => {
const { const {
claim, claim,
certificate, certificate,

View file

@ -25,12 +25,3 @@ export function doFetchCostInfoForUri(uri) {
} }
} }
export function doFetchCurrentUriCostInfo() {
return function(dispatch, getState) {
const state = getState()
const uri = selectCurrentUri(state)
dispatch(doFetchCostInfoForUri(uri))
}
}

View file

@ -11,90 +11,26 @@ import {
} from 'actions/app' } from 'actions/app'
import { import {
selectCurrentPage, selectCurrentPage,
selectSearchQuery,
} from 'selectors/app' } from 'selectors/app'
import {
selectSearchQuery,
} from 'selectors/search'
export function doSearchContent(query) { export function doSearch(query) {
return function(dispatch, getState) { return function(dispatch, getState) {
const state = getState() const state = getState()
const page = selectCurrentPage(state) const page = selectCurrentPage(state)
if (!query) { if (!query) {
return dispatch({ return dispatch({
type: types.SEARCH_CANCELLED, type: types.SEARCH_CANCELLED,
}) })
} }
dispatch({
type: types.SEARCH_STARTED,
data: { query }
})
if(page != 'search' && query != undefined) { if(page != 'search' && query != undefined) {
dispatch(doNavigate('search', { query: query })) return dispatch(doNavigate('search', { query: 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,
}
})
})
}
}
export function doActivateSearch() {
return function(dispatch, getState) {
const state = getState()
const page = selectCurrentPage(state)
const query = selectSearchQuery(state)
if(page != 'discover' && query != undefined) dispatch(doNavigate('discover'))
dispatch({
type: types.ACTIVATE_SEARCH,
})
}
}
export function doDeactivateSearch() {
return {
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({ dispatch({
type: types.SEARCH_STARTED, type: types.SEARCH_STARTED,

View file

@ -12,7 +12,6 @@ import {
doCheckUpgradeAvailable, doCheckUpgradeAvailable,
doOpenModal, doOpenModal,
doCloseModal, doCloseModal,
doSearch,
} from 'actions/app' } from 'actions/app'
import App from './view' import App from './view'

View file

@ -19,16 +19,12 @@ class App extends React.Component {
render() { render() {
const { const {
currentPage,
modal, modal,
headerLinks, headerLinks,
searchTerm,
} = this.props } = this.props
const searchQuery = (currentPage == 'discover' && searchTerm ? searchTerm : '')
return <div id="window"> return <div id="window">
<Header initialQuery={searchQuery} onSearch={() => { alert('header search'); }} <Header />
onSubmit={() => { alert('header submit'); }} links={headerLinks} />
<div id="main-content"> <div id="main-content">
<Router /> <Router />
</div> </div>

View file

@ -0,0 +1,29 @@
import React from 'react'
import {
connect,
} from 'react-redux'
import {
doSearch,
} from 'actions/search'
import {
selectIsSearching,
selectCurrentSearchResults,
selectSearchQuery,
} from 'selectors/search'
import {
doNavigate,
} from 'actions/app'
import FileListSearch from './view'
const select = (state) => ({
isSearching: selectIsSearching(state),
query: selectSearchQuery(state),
results: selectCurrentSearchResults(state)
})
const perform = (dispatch) => ({
navigate: (path) => dispatch(doNavigate(path)),
search: (search) => dispatch(doSearch(search))
})
export default connect(select, perform)(FileListSearch)

View file

@ -0,0 +1,70 @@
import React from 'react';
import lbry from 'lbry';
import lbryio from 'lbryio';
import lbryuri from 'lbryuri';
import lighthouse from 'lighthouse';
import FileTile from 'component/fileTile'
import Link from 'component/link'
import {ToolTip} from 'component/tooltip.js';
import {BusyMessage} from 'component/common.js';
const SearchNoResults = (props) => {
const {
navigate,
query,
} = props
return <section>
<span className="empty">
No one has checked anything in for {query} yet. { ' ' }
<Link label="Be the first" onClick={() => navigate('/publish')} />
</span>
</section>;
}
const FileListSearchResults = (props) => {
const {
results,
} = props
const rows = [],
seenNames = {}; //fix this when the search API returns claim IDs
for (let {name, claim, claim_id, channel_name, channel_id, txid, nout} of results) {
const uri = lbryuri.build({
channelName: channel_name,
contentName: name,
claimId: channel_id || claim_id,
});
rows.push(
<FileTile key={uri} uri={uri} />
);
}
return (
<div>{rows}</div>
);
}
class FileListSearch extends React.Component{
componentWillMount() {
this.props.search(this.props.query)
}
render() {
const {
isSearching,
results
} = this.props
return (
isSearching ?
<BusyMessage message="Looking up the Dewey Decimals" /> :
(results && results.length) ?
<FileListSearchResults {...this.props} /> :
<SearchNoResults {...this.props} />
)
}
}
export default FileListSearch

View file

@ -0,0 +1,25 @@
import React from 'react'
import {
connect
} from 'react-redux'
import {
doFetchTransactions,
} from 'actions/wallet'
import {
selectBalance,
selectTransactionItems,
selectIsFetchingTransactions,
} from 'selectors/wallet'
import TransactionList from './view'
const select = (state) => ({
fetchingTransactions: selectIsFetchingTransactions(state),
transactionItems: selectTransactionItems(state),
})
const perform = (dispatch) => ({
fetchTransactions: () => dispatch(doFetchTransactions())
})
export default connect(select, perform)(TransactionList)

View file

@ -0,0 +1,65 @@
import React from 'react';
import {
Address,
BusyMessage,
CreditAmount
} from 'component/common';
class TransactionList extends React.Component{
componentWillMount() {
this.props.fetchTransactions()
}
render() {
const {
fetchingTransactions,
transactionItems,
} = this.props
const rows = []
if (transactionItems.length > 0) {
transactionItems.forEach(function (item) {
rows.push(
<tr key={item.id}>
<td>{ (item.amount > 0 ? '+' : '' ) + item.amount }</td>
<td>{ item.date ? item.date.toLocaleDateString() : <span className="empty">(Transaction pending)</span> }</td>
<td>{ item.date ? item.date.toLocaleTimeString() : <span className="empty">(Transaction pending)</span> }</td>
<td>
<a className="button-text" href={"https://explorer.lbry.io/tx/"+item.id} target="_blank">{item.id.substr(0, 7)}</a>
</td>
</tr>
);
});
}
return (
<section className="card">
<div className="card__title-primary">
<h3>Transaction History</h3>
</div>
<div className="card__content">
{ fetchingTransactions && <BusyMessage message="Loading transactions" /> }
{ !fetchingTransactions && rows.length === 0 ? <div className="empty">You have no transactions.</div> : '' }
{ rows.length > 0 ?
<table className="table-standard table-stretch">
<thead>
<tr>
<th>Amount</th>
<th>Date</th>
<th>Time</th>
<th>Transaction</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
: ''
}
</div>
</section>
)
}
}
export default TransactionList

View file

@ -0,0 +1,25 @@
import React from 'react'
import {
connect
} from 'react-redux'
import {
doCheckAddressIsMine,
doGetNewAddress,
} from 'actions/wallet'
import {
selectReceiveAddress,
selectGettingNewAddress
} from 'selectors/wallet'
import WalletPage from './view'
const select = (state) => ({
receiveAddress: selectReceiveAddress(state),
gettingNewAddress: selectGettingNewAddress(state),
})
const perform = (dispatch) => ({
checkAddressIsMine: (address) => dispatch(doCheckAddressIsMine(address)),
getNewAddress: () => dispatch(doGetNewAddress()),
})
export default connect(select, perform)(WalletPage)

View file

@ -0,0 +1,41 @@
import React from 'react';
import Link from 'component/link';
import {
Address
} from 'component/common';
class WalletAddress extends React.Component {
componentWillMount() {
this.props.checkAddressIsMine(this.props.receiveAddress)
}
render() {
const {
receiveAddress,
getNewAddress,
gettingNewAddress,
} = this.props
return (
<section className="card">
<div className="card__title-primary">
<h3>Wallet Address</h3>
</div>
<div className="card__content">
<Address address={receiveAddress} />
</div>
<div className="card__actions">
<Link label="Get New Address" button="primary" icon='icon-refresh' onClick={getNewAddress} disabled={gettingNewAddress} />
</div>
<div className="card__content">
<div className="help">
<p>Other LBRY users may send credits to you by entering this address on the "Send" page.</p>
<p>You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.</p>
</div>
</div>
</section>
);
}
}
export default WalletAddress

View file

@ -0,0 +1,36 @@
import React from 'react'
import {
connect
} from 'react-redux'
import {
doCloseModal,
} from 'actions/app'
import {
doSendDraftTransaction,
doSetDraftTransactionAmount,
doSetDraftTransactionAddress,
} from 'actions/wallet'
import {
selectCurrentModal,
} from 'selectors/app'
import {
selectDraftTransactionAmount,
selectDraftTransactionAddress,
} from 'selectors/wallet'
import WalletSend from './view'
const select = (state) => ({
modal: selectCurrentModal(state),
address: selectDraftTransactionAddress(state),
amount: selectDraftTransactionAmount(state),
})
const perform = (dispatch) => ({
closeModal: () => dispatch(doCloseModal()),
sendToAddress: () => dispatch(doSendDraftTransaction()),
setAmount: (event) => dispatch(doSetDraftTransactionAmount(event.target.value)),
setAddress: (event) => dispatch(doSetDraftTransactionAddress(event.target.value)),
})
export default connect(select, perform)(WalletSend)

View file

@ -0,0 +1,49 @@
import React from 'react';
import Link from 'component/link';
import Modal from 'component/modal';
import {
FormRow
} from 'component/form';
const WalletSend = (props) => {
const {
sendToAddress,
closeModal,
modal,
setAmount,
setAddress,
amount,
address,
} = props
return (
<section className="card">
<form onSubmit={sendToAddress}>
<div className="card__title-primary">
<h3>Send Credits</h3>
</div>
<div className="card__content">
<FormRow label="Amount" postfix="LBC" step="0.01" type="number" placeholder="1.23" size="10" onChange={setAmount} value={amount} />
</div>
<div className="card__content">
<FormRow label="Recipient Address" placeholder="bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs" type="text" size="60" onChange={setAddress} value={address} />
</div>
<div className="card__actions card__actions--form-submit">
<Link button="primary" label="Send" onClick={sendToAddress} disabled={!(parseFloat(amount) > 0.0) || !address} />
<input type='submit' className='hidden' />
</div>
</form>
{modal == 'insufficientBalance' && <Modal isOpen={true} contentLabel="Insufficient balance" onConfirmed={closeModal}>
Insufficient balance: after this transaction you would have less than 1 LBC in your wallet.
</Modal>}
{modal == 'transactionSuccessful' && <Modal isOpen={true} contentLabel="Transaction successful" onConfirmed={closeModal}>
Your transaction was successfully placed in the queue.
</Modal>}
{modal == 'transactionFailed' && <Modal isOpen={true} contentLabel="Transaction failed" onConfirmed={closeModal}>
Something went wrong:
</Modal>}
</section>
)
}
export default WalletSend

View file

@ -6,15 +6,13 @@ import lbryuri from 'lbryuri.js'
import { import {
selectWunderBarAddress, selectWunderBarAddress,
selectWunderBarIcon selectWunderBarIcon
} from 'selectors/app' } from 'selectors/search'
import {
doSearch,
} from 'actions/search'
import { import {
doNavigate, doNavigate,
} from 'actions/app' } from 'actions/app'
import {
doSearchContent,
doActivateSearch,
doDeactivateSearch,
} from 'actions/search'
import Wunderbar from './view' import Wunderbar from './view'
const select = (state) => ({ const select = (state) => ({
@ -23,12 +21,7 @@ const select = (state) => ({
}) })
const perform = (dispatch) => ({ const perform = (dispatch) => ({
// navigate: (path) => dispatch(doNavigate(path)), onSearch: (query) => dispatch(doSearch(query)),
// 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) => dispatch(doNavigate('/show', { uri: lbryuri.normalize(query) } )) onSubmit: (query) => dispatch(doNavigate('/show', { uri: lbryuri.normalize(query) } ))
}) })

View file

@ -60,5 +60,3 @@ export const FETCH_MY_CLAIMS_COMPLETED = 'FETCH_MY_CLAIMS_COMPLETED'
export const SEARCH_STARTED = 'SEARCH_STARTED' export const SEARCH_STARTED = 'SEARCH_STARTED'
export const SEARCH_COMPLETED = 'SEARCH_COMPLETED' export const SEARCH_COMPLETED = 'SEARCH_COMPLETED'
export const SEARCH_CANCELLED = 'SEARCH_CANCELLED' export const SEARCH_CANCELLED = 'SEARCH_CANCELLED'
export const ACTIVATE_SEARCH = 'ACTIVATE_SEARCH'
export const DEACTIVATE_SEARCH = 'DEACTIVATE_SEARCH'

View file

@ -9,7 +9,6 @@ import SnackBar from './component/snack-bar.js';
import {AuthOverlay} from './component/auth.js'; import {AuthOverlay} from './component/auth.js';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import store from 'store.js'; import store from 'store.js';
import { runTriggers } from 'triggers'
import { import {
doDaemonReady, doDaemonReady,
doChangePath, doChangePath,
@ -41,8 +40,6 @@ ipcRenderer.on('open-uri-requested', (event, uri) => {
}); });
const initialState = app.store.getState(); const initialState = app.store.getState();
app.store.subscribe(runTriggers);
runTriggers();
var init = function() { var init = function() {

View file

@ -2,6 +2,9 @@ import React from 'react'
import { import {
connect connect
} from 'react-redux' } from 'react-redux'
import {
doFetchFeaturedUris,
} from 'actions/content'
import { import {
selectFeaturedUris, selectFeaturedUris,
selectFetchingFeaturedUris, selectFetchingFeaturedUris,
@ -14,6 +17,7 @@ const select = (state) => ({
}) })
const perform = (dispatch) => ({ const perform = (dispatch) => ({
fetchFeaturedUris: () => dispatch(doFetchFeaturedUris())
}) })
export default connect(select, perform)(DiscoverPage) export default connect(select, perform)(DiscoverPage)

View file

@ -23,28 +23,37 @@ const FeaturedCategory = (props) => {
</div> </div>
} }
const DiscoverPage = (props) => { class DiscoverPage extends React.Component{
componentWillMount() {
this.props.fetchFeaturedUris()
}
render() {
const { const {
featuredUris, featuredUris,
fetchingFeaturedUris, fetchingFeaturedUris,
} = props } = this.props
const failed = Object.keys(featuredUris).length === 0
let content let content
if (fetchingFeaturedUris) content = <BusyMessage message="Fetching content" /> if (fetchingFeaturedUris) {
if (!fetchingFeaturedUris && failed) content = <div className="empty">Failed to load landing content.</div> content = <BusyMessage message="Fetching content" />
if (!fetchingFeaturedUris && !failed) { } else {
if (typeof featuredUris === "object") {
content = Object.keys(featuredUris).map(category => { content = Object.keys(featuredUris).map(category => {
return featuredUris[category].length ? return featuredUris[category].length ?
<FeaturedCategory key={category} category={category} names={featuredUris[category]} /> : <FeaturedCategory key={category} category={category} names={featuredUris[category]} /> :
''; '';
}) })
} else if (featuredUris !== undefined) {
content = <div className="empty">Failed to load landing content.</div>
}
} }
return ( return (
<main>{content}</main> <main>{content}</main>
) )
} }
}
export default DiscoverPage; export default DiscoverPage;

View file

@ -2,6 +2,9 @@ import React from 'react'
import { import {
connect connect
} from 'react-redux' } from 'react-redux'
import {
doFetchDownloadedContent,
} from 'actions/content'
import { import {
selectFetchingDownloadedContent, selectFetchingDownloadedContent,
} from 'selectors/content' } from 'selectors/content'
@ -20,6 +23,7 @@ const select = (state) => ({
const perform = (dispatch) => ({ const perform = (dispatch) => ({
navigate: (path) => dispatch(doNavigate(path)), navigate: (path) => dispatch(doNavigate(path)),
fetchFileListDownloaded: () => dispatch(doFetchDownloadedContent()),
}) })
export default connect(select, perform)(FileListDownloaded) export default connect(select, perform)(FileListDownloaded)

View file

@ -11,6 +11,10 @@ import FileList from 'component/fileList'
import SubHeader from 'component/subHeader' import SubHeader from 'component/subHeader'
class FileListDownloaded extends React.Component { class FileListDownloaded extends React.Component {
componentWillMount() {
this.props.fetchFileListDownloaded()
}
render() { render() {
const { const {
downloadedContent, downloadedContent,
@ -28,7 +32,7 @@ class FileListDownloaded extends React.Component {
} }
return ( return (
<main className="page"> <main className="main--single-column">
<SubHeader /> <SubHeader />
{content} {content}
</main> </main>

View file

@ -2,6 +2,9 @@ import React from 'react'
import { import {
connect connect
} from 'react-redux' } from 'react-redux'
import {
doFetchPublishedContent,
} from 'actions/content'
import { import {
selectFetchingPublishedContent, selectFetchingPublishedContent,
} from 'selectors/content' } from 'selectors/content'
@ -20,6 +23,7 @@ const select = (state) => ({
const perform = (dispatch) => ({ const perform = (dispatch) => ({
navigate: (path) => dispatch(doNavigate(path)), navigate: (path) => dispatch(doNavigate(path)),
fetchFileListPublished: () => dispatch(doFetchPublishedContent()),
}) })
export default connect(select, perform)(FileListPublished) export default connect(select, perform)(FileListPublished)

View file

@ -11,6 +11,10 @@ import FileList from 'component/fileList'
import SubHeader from 'component/subHeader' import SubHeader from 'component/subHeader'
class FileListPublished extends React.Component { class FileListPublished extends React.Component {
componentWillMount() {
this.props.fetchFileListPublished()
}
componentDidUpdate() { componentDidUpdate() {
if(this.props.publishedContent.length > 0) this._requestPublishReward() if(this.props.publishedContent.length > 0) this._requestPublishReward()
} }
@ -49,7 +53,7 @@ class FileListPublished extends React.Component {
} }
return ( return (
<main className="page"> <main className="main--single-column">
<SubHeader /> <SubHeader />
{content} {content}
</main> </main>

View file

@ -2,17 +2,11 @@ import React from 'react'
import { import {
connect, connect,
} from 'react-redux' } from 'react-redux'
import {
doSearchContent,
} from 'actions/search'
import { import {
selectIsSearching, selectIsSearching,
selectCurrentSearchResults,
selectSearchActivated,
} from 'selectors/search'
import {
selectSearchQuery, selectSearchQuery,
} from 'selectors/app' selectCurrentSearchResults,
} from 'selectors/search'
import { import {
doNavigate, doNavigate,
} from 'actions/app' } from 'actions/app'
@ -22,7 +16,6 @@ const select = (state) => ({
isSearching: selectIsSearching(state), isSearching: selectIsSearching(state),
query: selectSearchQuery(state), query: selectSearchQuery(state),
results: selectCurrentSearchResults(state), results: selectCurrentSearchResults(state),
searchActive: selectSearchActivated(state),
}) })
const perform = (dispatch) => ({ const perform = (dispatch) => ({

View file

@ -1,89 +1,40 @@
import React from 'react'; import React from 'react';
import lbry from 'lbry';
import lbryio from 'lbryio';
import lbryuri from 'lbryuri'; import lbryuri from 'lbryuri';
import lighthouse from 'lighthouse';
import FileTile from 'component/fileTile' import FileTile from 'component/fileTile'
import Link from 'component/link' import FileListSearch from 'component/fileListSearch'
import {ToolTip} from 'component/tooltip.js'; import {ToolTip} from 'component/tooltip.js';
import {BusyMessage} from 'component/common.js'; import {BusyMessage} from 'component/common.js';
const SearchNoResults = (props) => {
const {
navigate,
query,
} = props
return <section> class SearchPage extends React.Component{
<span className="empty"> render() {
No one has checked anything in for {query} yet. { ' ' } console.log('searhc page render');
<Link label="Be the first" onClick={() => navigate('/publish')} /> console.log(this.props);
</span>
</section>;
}
const SearchResultList = (props) => { const isValidUri = (query) => true //FIXME
const {
results,
} = props
const rows = [],
seenNames = {}; //fix this when the search API returns claim IDs
for (let {name, claim, claim_id, channel_name, channel_id, txid, nout} of results) {
const uri = lbryuri.build({
channelName: channel_name,
contentName: name,
claimId: channel_id || claim_id,
});
rows.push(
<FileTile key={uri} uri={uri} />
);
}
return (
<div>{rows}</div>
);
}
const SearchResults = (props) => {
const {
isSearching,
results
} = props
return (
isSearching ?
<BusyMessage message="Looking up the Dewey Decimals" /> :
(results && results.length) ?
<SearchResultList {...props} /> :
<SearchNoResults {...props} />
)
}
const SearchPage = (props) => {
const isValidUri = (query) => true
const { const {
query, query,
} = props } = this.props
return ( return (
<main className="main--single-column"> <main className="main--single-column">
{ isValidUri(query) ? { isValidUri(query) ?
<section className="section-spaced"> <section className="section-spaced">
<h3 className="card-row__header"> <h3 className="card-row__header">
Exact URL Exact URL <ToolTip label="?" body="This is the resolution of a LBRY URL and not controlled by LBRY Inc."
<ToolTip label="?" body="This is the resolution of a LBRY URL and not controlled by LBRY Inc." className="tooltip--header" /> className="tooltip--header" />
</h3> </h3>
<FileTile uri={lbryuri.normalize(query)} showEmpty={FileTile.SHOW_EMPTY_PUBLISH} /> <FileTile uri={lbryuri.normalize(query)} showEmpty={FileTile.SHOW_EMPTY_PUBLISH} />
</section> : '' } </section> : '' }
<section className="section-spaced"> <section className="section-spaced">
<h3 className="card-row__header"> <h3 className="card-row__header">
Search Results for {query} Search Results for {query} <ToolTip label="?" body="These search results are provided by LBRY, Inc."
<ToolTip label="?" body="These search results are provided by LBRY, Inc." className="tooltip--header" /> className="tooltip--header" />
</h3> </h3>
<SearchResults {...props} /> <FileListSearch query={query} />
</section> </section>
</main> </main>
) )
} }
}
export default SearchPage; export default SearchPage;

View file

@ -5,9 +5,6 @@ import {
import { import {
doResolveUri, doResolveUri,
} from 'actions/content' } from 'actions/content'
import {
doNavigate,
} from 'actions/app'
import { import {
selectCurrentUri, selectCurrentUri,
} from 'selectors/app' } from 'selectors/app'
@ -43,7 +40,7 @@ const makeSelect = () => {
const perform = (dispatch) => ({ const perform = (dispatch) => ({
navigate: (path, params) => dispatch(doNavigate(path, params)), navigate: (path, params) => dispatch(doNavigate(path, params)),
resolveUri: (uri) => dispatch(doResolveUri(uri)), resolveUri: (uri) => dispatch(doResolveUri(uri))
}) })
export default connect(makeSelect, perform)(ShowPage) export default connect(makeSelect, perform)(ShowPage)

View file

@ -3,51 +3,16 @@ import {
connect connect
} from 'react-redux' } from 'react-redux'
import { import {
doCloseModal, selectCurrentPage
} from 'actions/app'
import {
doGetNewAddress,
doCheckAddressIsMine,
doSendDraftTransaction,
doSetDraftTransactionAmount,
doSetDraftTransactionAddress,
} from 'actions/wallet'
import {
selectCurrentPage,
selectCurrentModal,
} from 'selectors/app' } from 'selectors/app'
import { import {
selectBalance, selectBalance
selectTransactions,
selectTransactionItems,
selectIsFetchingTransactions,
selectReceiveAddress,
selectGettingNewAddress,
selectDraftTransactionAmount,
selectDraftTransactionAddress,
} from 'selectors/wallet' } from 'selectors/wallet'
import WalletPage from './view' import WalletPage from './view'
const select = (state) => ({ const select = (state) => ({
currentPage: selectCurrentPage(state), currentPage: selectCurrentPage(state),
balance: selectBalance(state), balance: selectBalance(state)
transactions: selectTransactions(state),
fetchingTransactions: selectIsFetchingTransactions(state),
transactionItems: selectTransactionItems(state),
receiveAddress: selectReceiveAddress(state),
gettingNewAddress: selectGettingNewAddress(state),
modal: selectCurrentModal(state),
address: selectDraftTransactionAddress(state),
amount: selectDraftTransactionAmount(state),
}) })
const perform = (dispatch) => ({ export default connect(select, null)(WalletPage)
closeModal: () => dispatch(doCloseModal()),
getNewAddress: () => dispatch(doGetNewAddress()),
checkAddressIsMine: (address) => dispatch(doCheckAddressIsMine(address)),
sendToAddress: () => dispatch(doSendDraftTransaction()),
setAmount: (event) => dispatch(doSetDraftTransactionAmount(event.target.value)),
setAddress: (event) => dispatch(doSetDraftTransactionAddress(event.target.value)),
})
export default connect(select, perform)(WalletPage)

View file

@ -1,245 +1,13 @@
import React from 'react'; import React from 'react';
import lbry from 'lbry.js';
import Link from 'component/link';
import Modal from 'component/modal';
import SubHeader from 'component/subHeader' import SubHeader from 'component/subHeader'
import TransactionList from 'component/transactionList'
import WalletAddress from 'component/walletAddress'
import WalletSend from 'component/walletSend'
import { import {
FormField,
FormRow
} from 'component/form';
import {
Address,
BusyMessage,
CreditAmount CreditAmount
} from 'component/common'; } from 'component/common';
class AddressSection extends React.Component {
componentWillMount() {
this.props.checkAddressIsMine(this.props.receiveAddress)
}
render() {
const {
receiveAddress,
getNewAddress,
gettingNewAddress,
} = this.props
return (
<section className="card">
<div className="card__title-primary">
<h3>Wallet Address</h3>
</div>
<div className="card__content">
<Address address={receiveAddress} />
</div>
<div className="card__actions">
<Link label="Get New Address" button="primary" icon='icon-refresh' onClick={getNewAddress} disabled={gettingNewAddress} />
</div>
<div className="card__content">
<div className="help">
<p>Other LBRY users may send credits to you by entering this address on the "Send" page.</p>
<p>You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.</p>
</div>
</div>
</section>
);
}
}
const SendToAddressSection = (props) => {
const {
sendToAddress,
closeModal,
modal,
setAmount,
setAddress,
amount,
address,
} = props
return (
<section className="card">
<form onSubmit={sendToAddress}>
<div className="card__title-primary">
<h3>Send Credits</h3>
</div>
<div className="card__content">
<FormRow label="Amount" postfix="LBC" step="0.01" type="number" placeholder="1.23" size="10" onChange={setAmount} value={amount} />
</div>
<div className="card__content">
<FormRow label="Recipient Address" placeholder="bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs" type="text" size="60" onChange={setAddress} value={address} />
</div>
<div className="card__actions card__actions--form-submit">
<Link button="primary" label="Send" onClick={sendToAddress} disabled={!(parseFloat(amount) > 0.0) || !address} />
<input type='submit' className='hidden' />
</div>
</form>
{modal == 'insufficientBalance' && <Modal isOpen={true} contentLabel="Insufficient balance" onConfirmed={closeModal}>
Insufficient balance: after this transaction you would have less than 1 LBC in your wallet.
</Modal>}
{modal == 'transactionSuccessful' && <Modal isOpen={true} contentLabel="Transaction successful" onConfirmed={closeModal}>
Your transaction was successfully placed in the queue.
</Modal>}
{modal == 'transactionFailed' && <Modal isOpen={true} contentLabel="Transaction failed" onConfirmed={closeModal}>
Something went wrong:
</Modal>}
</section>
)
}
// var SendToAddressSection = React.createClass({
// handleSubmit: function(event) {
// if (typeof event !== 'undefined') {
// event.preventDefault();
// }
// if ((this.state.balance - this.state.amount) < 1)
// {
// this.setState({
// modal: 'insufficientBalance',
// });
// return;
// }
// this.setState({
// results: "",
// });
// lbry.sendToAddress(this.state.amount, this.state.address, (results) => {
// if(results === true)
// {
// this.setState({
// results: "Your transaction was successfully placed in the queue.",
// });
// }
// else
// {
// this.setState({
// results: "Something went wrong: " + results
// });
// }
// }, (error) => {
// this.setState({
// results: "Something went wrong: " + error.message
// })
// });
// },
// closeModal: function() {
// this.setState({
// modal: null,
// });
// },
// getInitialState: function() {
// return {
// address: "",
// amount: 0.0,
// balance: <BusyMessage message="Checking balance" />,
// results: "",
// }
// },
// componentWillMount: function() {
// lbry.getBalance((results) => {
// this.setState({
// balance: results,
// });
// });
// },
// setAmount: function(event) {
// this.setState({
// amount: parseFloat(event.target.value),
// })
// },
// setAddress: function(event) {
// this.setState({
// address: event.target.value,
// })
// },
// render: function() {
// return (
// <section className="card">
// <form onSubmit={this.handleSubmit}>
// <div className="card__title-primary">
// <h3>Send Credits</h3>
// </div>
// <div className="card__content">
// <FormRow label="Amount" postfix="LBC" step="0.01" type="number" placeholder="1.23" size="10" onChange={this.setAmount} />
// </div>
// <div className="card__content">
// <FormRow label="Recipient Address" placeholder="bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs" type="text" size="60" onChange={this.setAddress} />
// </div>
// <div className="card__actions card__actions--form-submit">
// <Link button="primary" label="Send" onClick={this.handleSubmit} disabled={!(parseFloat(this.state.amount) > 0.0) || this.state.address == ""} />
// <input type='submit' className='hidden' />
// </div>
// {
// this.state.results ?
// <div className="card__content">
// <h4>Results</h4>
// {this.state.results}
// </div> : ''
// }
// </form>
// <Modal isOpen={this.state.modal === 'insufficientBalance'} contentLabel="Insufficient balance"
// onConfirmed={this.closeModal}>
// Insufficient balance: after this transaction you would have less than 1 LBC in your wallet.
// </Modal>
// </section>
// );
// }
// });
const TransactionList = (props) => {
const {
fetchingTransactions,
transactionItems,
} = props
const rows = []
if (transactionItems.length > 0) {
transactionItems.forEach(function(item) {
rows.push(
<tr key={item.id}>
<td>{ (item.amount > 0 ? '+' : '' ) + item.amount }</td>
<td>{ item.date ? item.date.toLocaleDateString() : <span className="empty">(Transaction pending)</span> }</td>
<td>{ item.date ? item.date.toLocaleTimeString() : <span className="empty">(Transaction pending)</span> }</td>
<td>
<a className="button-text" href={"https://explorer.lbry.io/tx/"+item.id} target="_blank">{item.id.substr(0, 7)}</a>
</td>
</tr>
);
});
}
return (
<section className="card">
<div className="card__title-primary">
<h3>Transaction History</h3>
</div>
<div className="card__content">
{ fetchingTransactions ? <BusyMessage message="Loading transactions" /> : '' }
{ !fetchingTransactions && rows.length === 0 ? <div className="empty">You have no transactions.</div> : '' }
{ rows.length > 0 ?
<table className="table-standard table-stretch">
<thead>
<tr>
<th>Amount</th>
<th>Date</th>
<th>Time</th>
<th>Transaction</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
: ''
}
</div>
</section>
)
}
const WalletPage = (props) => { const WalletPage = (props) => {
const { const {
balance, balance,
@ -258,8 +26,8 @@ const WalletPage = (props) => {
</div> </div>
</section> </section>
{ currentPage === 'wallet' ? <TransactionList {...props} /> : '' } { currentPage === 'wallet' ? <TransactionList {...props} /> : '' }
{ currentPage === 'send' ? <SendToAddressSection {...props} /> : '' } { currentPage === 'send' ? <WalletSend {...props} /> : '' }
{ currentPage === 'receive' ? <AddressSection {...props} /> : '' } { currentPage === 'receive' ? <WalletAddress /> : '' }
</main> </main>
) )
} }

View file

@ -16,7 +16,6 @@ reducers[types.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) {
success success
} = action.data } = action.data
return Object.assign({}, state, { return Object.assign({}, state, {
fetchingFeaturedContent: false, fetchingFeaturedContent: false,
fetchingFeaturedContentFailed: !success, fetchingFeaturedContentFailed: !success,

View file

@ -41,18 +41,6 @@ reducers[types.SEARCH_CANCELLED] = function(state, action) {
}) })
} }
reducers[types.ACTIVATE_SEARCH] = function(state, action) {
return Object.assign({}, state, {
activated: true,
})
}
reducers[types.DEACTIVATE_SEARCH] = function(state, action) {
return Object.assign({}, state, {
activated: false,
})
}
export default function reducer(state = defaultState, action) { export default function reducer(state = defaultState, action) {
const handler = reducers[action.type]; const handler = reducers[action.type];
if (handler) return handler(state, action); if (handler) return handler(state, action);

View file

@ -31,11 +31,6 @@ export const selectCurrentParams = createSelector(
} }
) )
export const selectSearchQuery = createSelector(
selectCurrentParams,
(params) => params.query
)
export const selectCurrentUri = createSelector( export const selectCurrentUri = createSelector(
selectCurrentPath, selectCurrentPath,
(path) => { (path) => {
@ -93,51 +88,6 @@ export const selectPageTitle = createSelector(
} }
) )
export const selectWunderBarAddress = createSelector(
selectPageTitle,
selectSearchQuery,
(title, query) => query || title
)
export const selectWunderBarIcon = createSelector(
selectCurrentPage,
selectCurrentUri,
(page, uri) => {
switch (page) {
case 'search':
return 'icon-search'
case 'settings':
return 'icon-gear'
case 'help':
return 'icon-question'
case 'report':
return 'icon-file'
case 'downloaded':
return 'icon-folder'
case 'published':
return 'icon-folder'
case 'start':
return 'icon-file'
case 'rewards':
return 'icon-bank'
case 'wallet':
case 'send':
case 'receive':
return 'icon-bank'
case 'show':
return 'icon-file'
case 'publish':
return 'icon-upload'
case 'developer':
return 'icon-file'
case 'developer':
return 'icon-code'
case 'discover':
return 'icon-home'
}
}
)
export const selectPlatform = createSelector( export const selectPlatform = createSelector(
_selectState, _selectState,
(state) => state.platform (state) => state.platform

View file

@ -57,18 +57,3 @@ export const selectAvailabilityForCurrentUri = createSelector(
selectAvailabilityByUri, selectAvailabilityByUri,
(uri, byUri) => byUri[uri] (uri, byUri) => byUri[uri]
) )
export const shouldFetchCurrentUriAvailability = createSelector(
selectDaemonReady,
selectCurrentPage,
selectFetchingAvailabilityForCurrentUri,
selectAvailabilityForCurrentUri,
(daemonReady, page, fetching, availability) => {
if (!daemonReady) return false
if (page != 'show') return false
if (fetching) return false
if (availability) return false
return true
}
)

View file

@ -9,7 +9,7 @@ export const _selectState = state => state.content || {}
export const selectFeaturedUris = createSelector( export const selectFeaturedUris = createSelector(
_selectState, _selectState,
(state) => state.featuredUris || {} (state) => state.featuredUris
) )
export const selectFetchingFeaturedUris = createSelector( export const selectFetchingFeaturedUris = createSelector(
@ -17,21 +17,6 @@ export const selectFetchingFeaturedUris = createSelector(
(state) => !!state.fetchingFeaturedContent (state) => !!state.fetchingFeaturedContent
) )
export const shouldFetchFeaturedUris = createSelector(
selectDaemonReady,
selectCurrentPage,
selectFetchingFeaturedUris,
selectFeaturedUris,
(daemonReady, page, fetching, byCategory) => {
if (!daemonReady) return false
if (page != 'discover') return false
if (fetching) return false
if (Object.keys(byCategory).length != 0) return false
return true
}
)
export const selectFetchingFileInfos = createSelector( export const selectFetchingFileInfos = createSelector(
_selectState, _selectState,
(state) => state.fetchingFileInfos || {} (state) => state.fetchingFileInfos || {}
@ -52,21 +37,6 @@ export const selectDownloadedContentFileInfos = createSelector(
(downloadedContent) => downloadedContent.fileInfos || [] (downloadedContent) => downloadedContent.fileInfos || []
) )
export const shouldFetchDownloadedContent = createSelector(
selectDaemonReady,
selectCurrentPage,
selectFetchingDownloadedContent,
selectDownloadedContent,
(daemonReady, page, fetching, content) => {
if (!daemonReady) return false
if (page != 'downloaded') return false
if (fetching) return false
if (Object.keys(content).length != 0) return false
return true
}
)
export const selectFetchingPublishedContent = createSelector( export const selectFetchingPublishedContent = createSelector(
_selectState, _selectState,
(state) => !!state.fetchingPublishedContent (state) => !!state.fetchingPublishedContent
@ -77,20 +47,6 @@ export const selectPublishedContent = createSelector(
(state) => state.publishedContent || {} (state) => state.publishedContent || {}
) )
export const shouldFetchPublishedContent = createSelector(
selectDaemonReady,
selectCurrentPage,
selectFetchingPublishedContent,
selectPublishedContent,
(daemonReady, page, fetching, content) => {
if (!daemonReady) return false
if (page != 'published') return false
if (fetching) return false
if (Object.keys(content).length != 0) return false
return true
}
)
export const selectResolvingUris = createSelector( export const selectResolvingUris = createSelector(
_selectState, _selectState,

View file

@ -28,20 +28,6 @@ export const selectFetchingCurrentUriCostInfo = createSelector(
(uri, byUri) => !!byUri[uri] (uri, byUri) => !!byUri[uri]
) )
export const shouldFetchCurrentUriCostInfo = createSelector(
selectCurrentPage,
selectCurrentUri,
selectFetchingCurrentUriCostInfo,
selectCurrentUriCostInfo,
(page, uri, fetching, costInfo) => {
if (page != 'show') return false
if (fetching) return false
if (Object.keys(costInfo).length != 0) return false
return true
}
)
const selectCostInfoForUri = (state, props) => { const selectCostInfoForUri = (state, props) => {
return selectAllCostInfoByUri(state)[props.uri] return selectAllCostInfoByUri(state)[props.uri]
} }

View file

@ -65,27 +65,6 @@ export const selectCurrentUriIsDownloaded = createSelector(
} }
) )
export const shouldFetchCurrentUriFileInfo = createSelector(
selectCurrentPage,
selectCurrentUri,
selectFetchingCurrentUriFileInfo,
selectCurrentUriFileInfo,
(page, uri, fetching, fileInfo) => {
console.log('should fetch?');
console.log(page);
console.log(uri);
console.log(fetching);
if (page != 'show') return false
if (fetching) return false
if (fileInfo != undefined) return false
console.log('fetch!');
return true
}
)
const selectFileInfoForUri = (state, props) => { const selectFileInfoForUri = (state, props) => {
return selectAllFileInfoByUri(state)[props.uri] return selectAllFileInfoByUri(state)[props.uri]
} }

View file

@ -2,11 +2,18 @@ import { createSelector } from 'reselect'
import { import {
selectCurrentParams, selectCurrentParams,
selectDaemonReady, selectDaemonReady,
selectSearchQuery, selectPageTitle,
selectCurrentPage,
selectCurrentUri
} from 'selectors/app' } from 'selectors/app'
export const _selectState = state => state.search || {} export const _selectState = state => state.search || {}
export const selectSearchQuery = createSelector(
selectCurrentParams,
(params) => params.query
)
export const selectIsSearching = createSelector( export const selectIsSearching = createSelector(
_selectState, _selectState,
(state) => !!state.searching (state) => !!state.searching
@ -25,25 +32,51 @@ export const selectSearchResultsByQuery = createSelector(
export const selectCurrentSearchResults = createSelector( export const selectCurrentSearchResults = createSelector(
selectSearchQuery, selectSearchQuery,
selectSearchResultsByQuery, selectSearchResultsByQuery,
(query, byQuery) => byQuery[query] || [] (query, byQuery) => byQuery[query]
) )
export const selectSearchActivated = createSelector(
_selectState,
(state) => !!state.activated
)
export const shouldSearch = createSelector( export const selectWunderBarAddress = createSelector(
selectDaemonReady, selectPageTitle,
selectSearchQuery, selectSearchQuery,
selectIsSearching, (title, query) => query || title
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 export const selectWunderBarIcon = createSelector(
selectCurrentPage,
selectCurrentUri,
(page, uri) => {
switch (page) {
case 'search':
return 'icon-search'
case 'settings':
return 'icon-gear'
case 'help':
return 'icon-question'
case 'report':
return 'icon-file'
case 'downloaded':
return 'icon-folder'
case 'published':
return 'icon-folder'
case 'start':
return 'icon-file'
case 'rewards':
return 'icon-bank'
case 'wallet':
case 'send':
case 'receive':
return 'icon-bank'
case 'show':
return 'icon-file'
case 'publish':
return 'icon-upload'
case 'developer':
return 'icon-file'
case 'developer':
return 'icon-code'
case 'discover':
return 'icon-home'
}
} }
) )

View file

@ -43,19 +43,6 @@ export const selectIsFetchingTransactions = createSelector(
(state) => state.fetchingTransactions (state) => state.fetchingTransactions
) )
export const shouldFetchTransactions = createSelector(
selectCurrentPage,
selectTransactions,
selectIsFetchingTransactions,
(page, transactions, fetching) => {
if (page != 'wallet') return false
if (fetching) return false
if (transactions.length != 0) return false
return true
}
)
export const selectReceiveAddress = createSelector( export const selectReceiveAddress = createSelector(
_selectState, _selectState,
(state) => state.receiveAddress (state) => state.receiveAddress
@ -66,19 +53,6 @@ export const selectGettingNewAddress = createSelector(
(state) => state.gettingNewAddress (state) => state.gettingNewAddress
) )
export const shouldGetReceiveAddress = createSelector(
selectReceiveAddress,
selectGettingNewAddress,
selectDaemonReady,
(address, fetching, daemonReady) => {
if (!daemonReady) return false
if (fetching) return false
if (address) return false
return true
}
)
export const shouldCheckAddressIsMine = createSelector( export const shouldCheckAddressIsMine = createSelector(
_selectState, _selectState,
selectCurrentPage, selectCurrentPage,

View file

@ -62,12 +62,12 @@ const reducers = redux.combineReducers({
const bulkThunk = createBulkThunkMiddleware() const bulkThunk = createBulkThunkMiddleware()
const middleware = [thunk, bulkThunk] const middleware = [thunk, bulkThunk]
if (env === 'development') { // if (env === 'development') {
const logger = createLogger({ // const logger = createLogger({
collapsed: true // collapsed: true
}); // });
middleware.push(logger) // middleware.push(logger)
} // }
const createStoreWithMiddleware = redux.compose( const createStoreWithMiddleware = redux.compose(
redux.applyMiddleware(...middleware) redux.applyMiddleware(...middleware)

View file

@ -1,102 +0,0 @@
import {
shouldFetchTransactions,
shouldGetReceiveAddress,
} from 'selectors/wallet'
import {
shouldFetchFeaturedUris,
shouldFetchDownloadedContent,
shouldFetchPublishedContent,
} from 'selectors/content'
import {
shouldFetchCurrentUriFileInfo,
} from 'selectors/file_info'
import {
shouldFetchCurrentUriCostInfo,
} from 'selectors/cost_info'
import {
shouldFetchCurrentUriAvailability,
} from 'selectors/availability'
import {
doFetchTransactions,
doGetNewAddress,
} from 'actions/wallet'
import {
doFetchFeaturedUris,
doFetchDownloadedContent,
doFetchPublishedContent,
} from 'actions/content'
import {
doFetchCurrentUriFileInfo,
} from 'actions/file_info'
import {
doFetchCurrentUriCostInfo,
} from 'actions/cost_info'
import {
doFetchCurrentUriAvailability,
} from 'actions/availability'
import {
shouldSearch,
} from 'selectors/search'
import {
doSearch,
} from 'actions/search'
const triggers = []
triggers.push({
selector: shouldFetchTransactions,
action: doFetchTransactions,
})
triggers.push({
selector: shouldGetReceiveAddress,
action: doGetNewAddress
})
triggers.push({
selector: shouldFetchFeaturedUris,
action: doFetchFeaturedUris,
})
triggers.push({
selector: shouldFetchDownloadedContent,
action: doFetchDownloadedContent,
})
triggers.push({
selector: shouldFetchPublishedContent,
action: doFetchPublishedContent,
})
triggers.push({
selector: shouldFetchCurrentUriFileInfo,
action: doFetchCurrentUriFileInfo,
})
triggers.push({
selector: shouldFetchCurrentUriCostInfo,
action: doFetchCurrentUriCostInfo,
})
triggers.push({
selector: shouldFetchCurrentUriAvailability,
action: doFetchCurrentUriAvailability,
})
triggers.push({
selector: shouldSearch,
action: doSearch,
})
const runTriggers = function() {
triggers.forEach(function(trigger) {
const state = app.store.getState();
const should = trigger.selector(state)
if (trigger.selector(state)) app.store.dispatch(trigger.action())
});
}
module.exports = {
triggers: triggers,
runTriggers: runTriggers
}