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)
url = `${url}?${queryStringFromParams(params)}`
console.log('Path: ' + url);
dispatch(doChangePath(url))
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() {
return {
type: types.DAEMON_READY

View file

@ -40,7 +40,7 @@ export function doResolveUri(uri) {
data: { uri }
})
lbry.resolve({ uri }).then((resolutionInfo) => {
return lbry.resolve({ uri }).then((resolutionInfo) => {
const {
claim,
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'
import {
selectCurrentPage,
selectSearchQuery,
} from 'selectors/app'
import {
selectSearchQuery,
} from 'selectors/search'
export function doSearchContent(query) {
export function doSearch(query) {
return function(dispatch, getState) {
const state = getState()
const page = selectCurrentPage(state)
if (!query) {
return dispatch({
type: types.SEARCH_CANCELLED,
})
}
dispatch({
type: types.SEARCH_STARTED,
data: { query }
})
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({
type: types.SEARCH_STARTED,

View file

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

View file

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

View file

@ -63,7 +63,7 @@ class FileCard extends React.Component {
<UriIndicator uri={uri} />
</div>
</div>
{metadata && metadata.thumbnail &&
{metadata && metadata.thumbnail &&
<div className="card__media" style={{ backgroundImage: "url('" + metadata.thumbnail + "')" }}></div>
}
<div className="card__content card__subtext card__subtext--two-lines">

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 {
selectWunderBarAddress,
selectWunderBarIcon
} from 'selectors/app'
} from 'selectors/search'
import {
doSearch,
} from 'actions/search'
import {
doNavigate,
} from 'actions/app'
import {
doSearchContent,
doActivateSearch,
doDeactivateSearch,
} from 'actions/search'
import Wunderbar from './view'
const select = (state) => ({
@ -23,12 +21,7 @@ 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(doNavigate('/search', { query })),
onSearch: (query) => dispatch(doSearch(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_COMPLETED = 'SEARCH_COMPLETED'
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 { Provider } from 'react-redux';
import store from 'store.js';
import { runTriggers } from 'triggers'
import {
doDaemonReady,
doChangePath,
@ -41,8 +40,6 @@ ipcRenderer.on('open-uri-requested', (event, uri) => {
});
const initialState = app.store.getState();
app.store.subscribe(runTriggers);
runTriggers();
var init = function() {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,89 +1,40 @@
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 FileListSearch from 'component/fileListSearch'
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>;
}
class SearchPage extends React.Component{
render() {
console.log('searhc page render');
console.log(this.props);
const SearchResultList = (props) => {
const {
results,
} = props
const isValidUri = (query) => true //FIXME
const {
query,
} = this.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 {
query,
} = props
return (
<main className="main--single-column">
{ isValidUri(query) ?
return (
<main className="main--single-column">
{ isValidUri(query) ?
<section className="section-spaced">
<h3 className="card-row__header">
Exact URL <ToolTip label="?" body="This is the resolution of a LBRY URL and not controlled by LBRY Inc."
className="tooltip--header" />
</h3>
<FileTile uri={lbryuri.normalize(query)} showEmpty={FileTile.SHOW_EMPTY_PUBLISH} />
</section> : '' }
<section className="section-spaced">
<h3 className="card-row__header">
Exact URL
<ToolTip label="?" body="This is the resolution of a LBRY URL and not controlled by LBRY Inc." className="tooltip--header" />
Search Results for {query} <ToolTip label="?" body="These search results are provided by LBRY, Inc."
className="tooltip--header" />
</h3>
<FileTile uri={lbryuri.normalize(query)} showEmpty={FileTile.SHOW_EMPTY_PUBLISH} />
</section> : '' }
<section className="section-spaced">
<h3 className="card-row__header">
Search Results for {query}
<ToolTip label="?" body="These search results are provided by LBRY, Inc." className="tooltip--header" />
</h3>
<SearchResults {...props} />
</section>
</main>
)
<FileListSearch query={query} />
</section>
</main>
)
}
}
export default SearchPage;

View file

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

View file

@ -3,51 +3,16 @@ import {
connect
} from 'react-redux'
import {
doCloseModal,
} from 'actions/app'
import {
doGetNewAddress,
doCheckAddressIsMine,
doSendDraftTransaction,
doSetDraftTransactionAmount,
doSetDraftTransactionAddress,
} from 'actions/wallet'
import {
selectCurrentPage,
selectCurrentModal,
selectCurrentPage
} from 'selectors/app'
import {
selectBalance,
selectTransactions,
selectTransactionItems,
selectIsFetchingTransactions,
selectReceiveAddress,
selectGettingNewAddress,
selectDraftTransactionAmount,
selectDraftTransactionAddress,
selectBalance
} from 'selectors/wallet'
import WalletPage from './view'
const select = (state) => ({
currentPage: selectCurrentPage(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),
balance: selectBalance(state)
})
const perform = (dispatch) => ({
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)
export default connect(select, null)(WalletPage)

View file

@ -1,245 +1,13 @@
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 TransactionList from 'component/transactionList'
import WalletAddress from 'component/walletAddress'
import WalletSend from 'component/walletSend'
import {
FormField,
FormRow
} from 'component/form';
import {
Address,
BusyMessage,
CreditAmount
} 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 {
balance,
@ -258,8 +26,8 @@ const WalletPage = (props) => {
</div>
</section>
{ currentPage === 'wallet' ? <TransactionList {...props} /> : '' }
{ currentPage === 'send' ? <SendToAddressSection {...props} /> : '' }
{ currentPage === 'receive' ? <AddressSection {...props} /> : '' }
{ currentPage === 'send' ? <WalletSend {...props} /> : '' }
{ currentPage === 'receive' ? <WalletAddress /> : '' }
</main>
)
}

View file

@ -16,7 +16,6 @@ reducers[types.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) {
success
} = action.data
return Object.assign({}, state, {
fetchingFeaturedContent: false,
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) {
const handler = reducers[action.type];
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(
selectCurrentPath,
(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(
_selectState,
(state) => state.platform

View file

@ -56,19 +56,4 @@ export const selectAvailabilityForCurrentUri = createSelector(
selectCurrentUri,
selectAvailabilityByUri,
(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(
_selectState,
(state) => state.featuredUris || {}
(state) => state.featuredUris
)
export const selectFetchingFeaturedUris = createSelector(
@ -17,21 +17,6 @@ export const selectFetchingFeaturedUris = createSelector(
(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(
_selectState,
(state) => state.fetchingFileInfos || {}
@ -52,21 +37,6 @@ export const selectDownloadedContentFileInfos = createSelector(
(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(
_selectState,
(state) => !!state.fetchingPublishedContent
@ -77,20 +47,6 @@ export const selectPublishedContent = createSelector(
(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(
_selectState,

View file

@ -28,20 +28,6 @@ export const selectFetchingCurrentUriCostInfo = createSelector(
(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) => {
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) => {
return selectAllFileInfoByUri(state)[props.uri]
}

View file

@ -2,11 +2,18 @@ import { createSelector } from 'reselect'
import {
selectCurrentParams,
selectDaemonReady,
selectSearchQuery,
selectPageTitle,
selectCurrentPage,
selectCurrentUri
} from 'selectors/app'
export const _selectState = state => state.search || {}
export const selectSearchQuery = createSelector(
selectCurrentParams,
(params) => params.query
)
export const selectIsSearching = createSelector(
_selectState,
(state) => !!state.searching
@ -25,25 +32,51 @@ export const selectSearchResultsByQuery = createSelector(
export const selectCurrentSearchResults = createSelector(
selectSearchQuery,
selectSearchResultsByQuery,
(query, byQuery) => byQuery[query] || []
(query, byQuery) => byQuery[query]
)
export const selectSearchActivated = createSelector(
_selectState,
(state) => !!state.activated
)
export const shouldSearch = createSelector(
selectDaemonReady,
export const selectWunderBarAddress = createSelector(
selectPageTitle,
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
}
(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'
}
}
)

View file

@ -43,19 +43,6 @@ export const selectIsFetchingTransactions = createSelector(
(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(
_selectState,
(state) => state.receiveAddress
@ -66,19 +53,6 @@ export const selectGettingNewAddress = createSelector(
(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(
_selectState,
selectCurrentPage,

View file

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