diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index bf0451c82..e8b13cf1c 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -1,238 +1,235 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' +import * as types from 'constants/action_types'; +import lbry from 'lbry'; import { - selectUpdateUrl, - selectUpgradeDownloadPath, - selectUpgradeDownloadItem, - selectUpgradeFilename, - selectPageTitle, - selectCurrentPage, - selectCurrentParams, -} from 'selectors/app' -import { - doSearch, -} from 'actions/search' + selectUpdateUrl, + selectUpgradeDownloadPath, + selectUpgradeDownloadItem, + selectUpgradeFilename, + selectPageTitle, + selectCurrentPage, + selectCurrentParams +} from 'selectors/app'; +import { doSearch } from 'actions/search'; -const {remote, ipcRenderer, shell} = require('electron'); +const { remote, ipcRenderer, shell } = require('electron'); const path = require('path'); const app = require('electron').remote.app; -const {download} = remote.require('electron-dl'); +const { download } = remote.require('electron-dl'); const fs = remote.require('fs'); -const queryStringFromParams = (params) => { - return Object - .keys(params) - .map(key => `${key}=${params[key]}`) - .join('&') -} +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)}` + return function(dispatch, getState) { + let url = path; + if (params) url = `${url}?${queryStringFromParams(params)}`; - dispatch(doChangePath(url)) + dispatch(doChangePath(url)); - const state = getState() - const pageTitle = selectPageTitle(state) - dispatch(doHistoryPush(params, pageTitle, url)) - } + const state = getState(); + const pageTitle = selectPageTitle(state); + dispatch(doHistoryPush(params, pageTitle, url)); + }; } export function doChangePath(path) { - return function(dispatch, getState) { - dispatch({ - type: types.CHANGE_PATH, - data: { - path, - } - }) + return function(dispatch, getState) { + dispatch({ + type: types.CHANGE_PATH, + data: { + path + } + }); - const state = getState() - const pageTitle = selectPageTitle(state) - window.document.title = pageTitle - window.scrollTo(0, 0) + const state = getState(); + const pageTitle = selectPageTitle(state); + window.document.title = pageTitle; + window.scrollTo(0, 0); - const currentPage = selectCurrentPage(state) - if (currentPage === 'search') { - const params = selectCurrentParams(state) - dispatch(doSearch(params.query)) - } - } + const currentPage = selectCurrentPage(state); + if (currentPage === 'search') { + const params = selectCurrentParams(state); + dispatch(doSearch(params.query)); + } + }; } export function doHistoryBack() { - return function(dispatch, getState) { - history.back() - } + return function(dispatch, getState) { + history.back(); + }; } export function doHistoryPush(params, title, relativeUrl) { - return function(dispatch, getState) { - let pathParts = window.location.pathname.split('/') - pathParts[pathParts.length - 1] = relativeUrl.replace(/^\//, '') - const url = pathParts.join('/') - title += " - LBRY" - history.pushState(params, title, url) - } + return function(dispatch, getState) { + let pathParts = window.location.pathname.split('/'); + pathParts[pathParts.length - 1] = relativeUrl.replace(/^\//, ''); + const url = pathParts.join('/'); + title += ' - LBRY'; + history.pushState(params, title, url); + }; } export function doOpenModal(modal) { - return { - type: types.OPEN_MODAL, - data: { - modal - } - } + return { + type: types.OPEN_MODAL, + data: { + modal + } + }; } export function doCloseModal() { - return { - type: types.CLOSE_MODAL, - } + return { + type: types.CLOSE_MODAL + }; } export function doUpdateDownloadProgress(percent) { - return { - type: types.UPGRADE_DOWNLOAD_PROGRESSED, - data: { - percent: percent - } - } + return { + type: types.UPGRADE_DOWNLOAD_PROGRESSED, + data: { + percent: percent + } + }; } export function doSkipUpgrade() { - return { - type: types.SKIP_UPGRADE - } + return { + type: types.SKIP_UPGRADE + }; } export function doStartUpgrade() { - return function(dispatch, getState) { - const state = getState() - const upgradeDownloadPath = selectUpgradeDownloadPath(state) + return function(dispatch, getState) { + const state = getState(); + const upgradeDownloadPath = selectUpgradeDownloadPath(state); - ipcRenderer.send('upgrade', upgradeDownloadPath) - } + ipcRenderer.send('upgrade', upgradeDownloadPath); + }; } export function doDownloadUpgrade() { - return function(dispatch, getState) { - const state = getState() - // Make a new directory within temp directory so the filename is guaranteed to be available - const dir = fs.mkdtempSync(app.getPath('temp') + require('path').sep); - const upgradeFilename = selectUpgradeFilename(state) + return function(dispatch, getState) { + const state = getState(); + // Make a new directory within temp directory so the filename is guaranteed to be available + const dir = fs.mkdtempSync(app.getPath('temp') + require('path').sep); + const upgradeFilename = selectUpgradeFilename(state); - let options = { - onProgress: (p) => dispatch(doUpdateDownloadProgress(Math.round(p * 100))), - directory: dir, - }; - download(remote.getCurrentWindow(), selectUpdateUrl(state), options) - .then(downloadItem => { - /** + let options = { + onProgress: p => dispatch(doUpdateDownloadProgress(Math.round(p * 100))), + directory: dir + }; + download( + remote.getCurrentWindow(), + selectUpdateUrl(state), + options + ).then(downloadItem => { + /** * TODO: get the download path directly from the download object. It should just be * downloadItem.getSavePath(), but the copy on the main process is being garbage collected * too soon. */ - dispatch({ - type: types.UPGRADE_DOWNLOAD_COMPLETED, - data: { - downloadItem, - path: path.join(dir, upgradeFilename) - } - }) - }); + dispatch({ + type: types.UPGRADE_DOWNLOAD_COMPLETED, + data: { + downloadItem, + path: path.join(dir, upgradeFilename) + } + }); + }); - dispatch({ - type: types.UPGRADE_DOWNLOAD_STARTED - }) - dispatch({ - type: types.OPEN_MODAL, - data: { - modal: 'downloading' - } - }) - } + dispatch({ + type: types.UPGRADE_DOWNLOAD_STARTED + }); + dispatch({ + type: types.OPEN_MODAL, + data: { + modal: 'downloading' + } + }); + }; } export function doCancelUpgrade() { - return function(dispatch, getState) { - const state = getState() - const upgradeDownloadItem = selectUpgradeDownloadItem(state) + return function(dispatch, getState) { + const state = getState(); + const upgradeDownloadItem = selectUpgradeDownloadItem(state); - if (upgradeDownloadItem) { - /* + if (upgradeDownloadItem) { + /* * Right now the remote reference to the download item gets garbage collected as soon as the * the download is over (maybe even earlier), so trying to cancel a finished download may * throw an error. */ - try { - upgradeDownloadItem.cancel(); - } catch (err) { - console.error(err) - // Do nothing - } - } + try { + upgradeDownloadItem.cancel(); + } catch (err) { + console.error(err); + // Do nothing + } + } - dispatch({ type: types.UPGRADE_CANCELLED }) - } + dispatch({ type: types.UPGRADE_CANCELLED }); + }; } export function doCheckUpgradeAvailable() { - return function(dispatch, getState) { - const state = getState() + return function(dispatch, getState) { + const state = getState(); - lbry.getAppVersionInfo().then(({remoteVersion, upgradeAvailable}) => { - if (upgradeAvailable) { - dispatch({ - type: types.UPDATE_VERSION, - data: { - version: remoteVersion, - } - }) - dispatch({ - type: types.OPEN_MODAL, - data: { - modal: 'upgrade' - } - }) - } - }); - } + lbry.getAppVersionInfo().then(({ remoteVersion, upgradeAvailable }) => { + if (upgradeAvailable) { + dispatch({ + type: types.UPDATE_VERSION, + data: { + version: remoteVersion + } + }); + dispatch({ + type: types.OPEN_MODAL, + data: { + modal: 'upgrade' + } + }); + } + }); + }; } export function doAlertError(errorList) { - return function(dispatch, getState) { - const state = getState() - console.log('do alert error') - console.log(errorList) - dispatch({ - type: types.OPEN_MODAL, - data: { - modal: 'error', - extraContent: errorList - } - }) - } + return function(dispatch, getState) { + const state = getState(); + console.log('do alert error'); + console.log(errorList); + dispatch({ + type: types.OPEN_MODAL, + data: { + modal: 'error', + extraContent: errorList + } + }); + }; } export function doDaemonReady() { - return { - type: types.DAEMON_READY - } + return { + type: types.DAEMON_READY + }; } export function doShowSnackBar(data) { - return { - type: types.SHOW_SNACKBAR, - data, - } + return { + type: types.SHOW_SNACKBAR, + data + }; } export function doRemoveSnackBarSnack() { - return { - type: types.REMOVE_SNACKBAR_SNACK, - } + return { + type: types.REMOVE_SNACKBAR_SNACK + }; } diff --git a/ui/js/actions/availability.js b/ui/js/actions/availability.js index 501a2eeda..856eff0aa 100644 --- a/ui/js/actions/availability.js +++ b/ui/js/actions/availability.js @@ -1,29 +1,27 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' -import { - selectFetchingAvailability -} from 'selectors/availability' +import * as types from 'constants/action_types'; +import lbry from 'lbry'; +import { selectFetchingAvailability } from 'selectors/availability'; export function doFetchAvailability(uri) { - return function(dispatch, getState) { - const state = getState() - const alreadyFetching = !!selectFetchingAvailability(state)[uri] + return function(dispatch, getState) { + const state = getState(); + const alreadyFetching = !!selectFetchingAvailability(state)[uri]; - if (!alreadyFetching) { - dispatch({ - type: types.FETCH_AVAILABILITY_STARTED, - data: {uri} - }) + if (!alreadyFetching) { + dispatch({ + type: types.FETCH_AVAILABILITY_STARTED, + data: { uri } + }); - lbry.get_availability({uri}).then((availability) => { - dispatch({ - type: types.FETCH_AVAILABILITY_COMPLETED, - data: { - availability, - uri, - } - }) - }) - } - } -} \ No newline at end of file + lbry.get_availability({ uri }).then(availability => { + dispatch({ + type: types.FETCH_AVAILABILITY_COMPLETED, + data: { + availability, + uri + } + }); + }); + } + }; +} diff --git a/ui/js/actions/content.js b/ui/js/actions/content.js index a7276abf9..6043699cd 100644 --- a/ui/js/actions/content.js +++ b/ui/js/actions/content.js @@ -1,294 +1,288 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' -import lbryio from 'lbryio' -import lbryuri from 'lbryuri' -import rewards from 'rewards' +import * as types from 'constants/action_types'; +import lbry from 'lbry'; +import lbryio from 'lbryio'; +import lbryuri from 'lbryuri'; +import rewards from 'rewards'; +import { selectBalance } from 'selectors/wallet'; import { - selectBalance, -} from 'selectors/wallet' -import { - selectFileInfoForUri, - selectUrisDownloading, -} from 'selectors/file_info' -import { - selectResolvingUris -} from 'selectors/content' -import { - selectCostInfoForUri, -} from 'selectors/cost_info' -import { - selectClaimsByUri, -} from 'selectors/claims' -import { - doOpenModal, -} from 'actions/app' + selectFileInfoForUri, + selectUrisDownloading +} from 'selectors/file_info'; +import { selectResolvingUris } from 'selectors/content'; +import { selectCostInfoForUri } from 'selectors/cost_info'; +import { selectClaimsByUri } from 'selectors/claims'; +import { doOpenModal } from 'actions/app'; export function doResolveUri(uri) { - return function(dispatch, getState) { + return function(dispatch, getState) { + uri = lbryuri.normalize(uri); - uri = lbryuri.normalize(uri) + const state = getState(); + const alreadyResolving = selectResolvingUris(state).indexOf(uri) !== -1; - const state = getState() - const alreadyResolving = selectResolvingUris(state).indexOf(uri) !== -1 + if (!alreadyResolving) { + dispatch({ + type: types.RESOLVE_URI_STARTED, + data: { uri } + }); - if (!alreadyResolving) { - dispatch({ - type: types.RESOLVE_URI_STARTED, - data: { uri } - }) + lbry.resolve({ uri }).then(resolutionInfo => { + const { claim, certificate } = resolutionInfo + ? resolutionInfo + : { claim: null, certificate: null }; - lbry.resolve({ uri }).then((resolutionInfo) => { - const { - claim, - certificate, - } = resolutionInfo ? resolutionInfo : { claim : null, certificate: null } - - dispatch({ - type: types.RESOLVE_URI_COMPLETED, - data: { - uri, - claim, - certificate, - } - }) - }) - } - } + dispatch({ + type: types.RESOLVE_URI_COMPLETED, + data: { + uri, + claim, + certificate + } + }); + }); + } + }; } export function doCancelResolveUri(uri) { - return function(dispatch, getState) { - lbry.cancelResolve({ uri }) - dispatch({ - type: types.RESOLVE_URI_CANCELED, - data: { uri } - }) - } + return function(dispatch, getState) { + lbry.cancelResolve({ uri }); + dispatch({ + type: types.RESOLVE_URI_CANCELED, + data: { uri } + }); + }; } export function doFetchFeaturedUris() { - return function(dispatch, getState) { - const state = getState() + return function(dispatch, getState) { + const state = getState(); - dispatch({ - type: types.FETCH_FEATURED_CONTENT_STARTED, - }) + dispatch({ + type: types.FETCH_FEATURED_CONTENT_STARTED + }); - const success = ({ Categories, Uris }) => { + const success = ({ Categories, Uris }) => { + let featuredUris = {}; - let featuredUris = {} + Categories.forEach(category => { + if (Uris[category] && Uris[category].length) { + featuredUris[category] = Uris[category]; + } + }); - Categories.forEach((category) => { - if (Uris[category] && Uris[category].length) { - featuredUris[category] = Uris[category] - } - }) + dispatch({ + type: types.FETCH_FEATURED_CONTENT_COMPLETED, + data: { + categories: Categories, + uris: featuredUris + } + }); + }; - dispatch({ - type: types.FETCH_FEATURED_CONTENT_COMPLETED, - data: { - categories: Categories, - uris: featuredUris, - } - }) - } + const failure = () => { + dispatch({ + type: types.FETCH_FEATURED_CONTENT_COMPLETED, + data: { + categories: [], + uris: {} + } + }); + }; - const failure = () => { - dispatch({ - type: types.FETCH_FEATURED_CONTENT_COMPLETED, - data: { - categories: [], - uris: {} - } - }) - } - - lbryio.call('discover', 'list', { version: "early-access" } ) - .then(success, failure) - } + lbryio + .call('discover', 'list', { version: 'early-access' }) + .then(success, failure); + }; } export function doUpdateLoadStatus(uri, outpoint) { - return function(dispatch, getState) { - const state = getState() + return function(dispatch, getState) { + const state = getState(); - lbry.file_list({ - outpoint: outpoint, - full_status: true, - }).then(([fileInfo]) => { - if(!fileInfo || fileInfo.written_bytes == 0) { - // download hasn't started yet - setTimeout(() => { dispatch(doUpdateLoadStatus(uri, outpoint)) }, 250) - } else if (fileInfo.completed) { - // TODO this isn't going to get called if they reload the client before - // the download finished - dispatch({ - type: types.DOWNLOADING_COMPLETED, - data: { - uri, - outpoint, - fileInfo, - } - }) - } else { - // ready to play - const { - total_bytes, - written_bytes, - } = fileInfo - const progress = (written_bytes / total_bytes) * 100 + lbry + .file_list({ + outpoint: outpoint, + full_status: true + }) + .then(([fileInfo]) => { + if (!fileInfo || fileInfo.written_bytes == 0) { + // download hasn't started yet + setTimeout(() => { + dispatch(doUpdateLoadStatus(uri, outpoint)); + }, 250); + } else if (fileInfo.completed) { + // TODO this isn't going to get called if they reload the client before + // the download finished + dispatch({ + type: types.DOWNLOADING_COMPLETED, + data: { + uri, + outpoint, + fileInfo + } + }); + } else { + // ready to play + const { total_bytes, written_bytes } = fileInfo; + const progress = written_bytes / total_bytes * 100; - dispatch({ - type: types.DOWNLOADING_PROGRESSED, - data: { - uri, - outpoint, - fileInfo, - progress, - } - }) - setTimeout(() => { dispatch(doUpdateLoadStatus(uri, outpoint)) }, 250) - } - }) - } + dispatch({ + type: types.DOWNLOADING_PROGRESSED, + data: { + uri, + outpoint, + fileInfo, + progress + } + }); + setTimeout(() => { + dispatch(doUpdateLoadStatus(uri, outpoint)); + }, 250); + } + }); + }; } export function doDownloadFile(uri, streamInfo) { - return function(dispatch, getState) { - const state = getState() + return function(dispatch, getState) { + const state = getState(); - lbry.file_list({ outpoint: streamInfo.outpoint, full_status: true }).then(([fileInfo]) => { - dispatch({ - type: types.DOWNLOADING_STARTED, - data: { - uri, - outpoint: streamInfo.outpoint, - fileInfo, - } - }) + lbry + .file_list({ outpoint: streamInfo.outpoint, full_status: true }) + .then(([fileInfo]) => { + dispatch({ + type: types.DOWNLOADING_STARTED, + data: { + uri, + outpoint: streamInfo.outpoint, + fileInfo + } + }); - dispatch(doUpdateLoadStatus(uri, streamInfo.outpoint)) - }) + dispatch(doUpdateLoadStatus(uri, streamInfo.outpoint)); + }); - lbryio.call('file', 'view', { - uri: uri, - outpoint: streamInfo.outpoint, - claim_id: streamInfo.claim_id, - }).catch(() => {}) + lbryio + .call('file', 'view', { + uri: uri, + outpoint: streamInfo.outpoint, + claim_id: streamInfo.claim_id + }) + .catch(() => {}); - rewards.claimEligiblePurchaseRewards() - - } + rewards.claimEligiblePurchaseRewards(); + }; } export function doLoadVideo(uri) { - return function(dispatch, getState) { - const state = getState() + return function(dispatch, getState) { + const state = getState(); - dispatch({ - type: types.LOADING_VIDEO_STARTED, - data: { - uri - } - }) + dispatch({ + type: types.LOADING_VIDEO_STARTED, + data: { + uri + } + }); - lbry.get({ uri }).then(streamInfo => { - const timeout = streamInfo === null || - typeof streamInfo !== 'object' || - streamInfo.error == 'Timeout' + lbry.get({ uri }).then(streamInfo => { + const timeout = + streamInfo === null || + typeof streamInfo !== 'object' || + streamInfo.error == 'Timeout'; - if(timeout) { - dispatch({ - type: types.LOADING_VIDEO_FAILED, - data: { uri } - }) - dispatch(doOpenModal('timedOut')) - } else { - dispatch(doDownloadFile(uri, streamInfo)) - } - }) - } + if (timeout) { + dispatch({ + type: types.LOADING_VIDEO_FAILED, + data: { uri } + }); + dispatch(doOpenModal('timedOut')); + } else { + dispatch(doDownloadFile(uri, streamInfo)); + } + }); + }; } export function doPurchaseUri(uri, purchaseModalName) { - return function(dispatch, getState) { - const state = getState() - const balance = selectBalance(state) - const fileInfo = selectFileInfoForUri(state, { uri }) - const downloadingByUri = selectUrisDownloading(state) - const alreadyDownloading = !!downloadingByUri[uri] + return function(dispatch, getState) { + const state = getState(); + const balance = selectBalance(state); + const fileInfo = selectFileInfoForUri(state, { uri }); + const downloadingByUri = selectUrisDownloading(state); + const alreadyDownloading = !!downloadingByUri[uri]; - // we already fully downloaded the file. - if (fileInfo && fileInfo.completed) { - // If written_bytes is false that means the user has deleted/moved the - // file manually on their file system, so we need to dispatch a - // doLoadVideo action to reconstruct the file from the blobs - if (!fileInfo.written_bytes) dispatch(doLoadVideo(uri)) + // we already fully downloaded the file. + if (fileInfo && fileInfo.completed) { + // If written_bytes is false that means the user has deleted/moved the + // file manually on their file system, so we need to dispatch a + // doLoadVideo action to reconstruct the file from the blobs + if (!fileInfo.written_bytes) dispatch(doLoadVideo(uri)); - return Promise.resolve() - } + return Promise.resolve(); + } - // we are already downloading the file - if (alreadyDownloading) { - return Promise.resolve() - } + // we are already downloading the file + if (alreadyDownloading) { + return Promise.resolve(); + } - const costInfo = selectCostInfoForUri(state, { uri }) - const { cost } = costInfo + const costInfo = selectCostInfoForUri(state, { uri }); + const { cost } = costInfo; - // the file is free or we have partially downloaded it - if (cost <= 0.01 || (fileInfo && fileInfo.download_directory)) { - dispatch(doLoadVideo(uri)) - return Promise.resolve() - } + // the file is free or we have partially downloaded it + if (cost <= 0.01 || (fileInfo && fileInfo.download_directory)) { + dispatch(doLoadVideo(uri)); + return Promise.resolve(); + } - if (cost > balance) { - dispatch(doOpenModal('notEnoughCredits')) - } else { - dispatch(doOpenModal(purchaseModalName)) - } + if (cost > balance) { + dispatch(doOpenModal('notEnoughCredits')); + } else { + dispatch(doOpenModal(purchaseModalName)); + } - return Promise.resolve() - } + return Promise.resolve(); + }; } export function doFetchClaimsByChannel(uri) { - return function(dispatch, getState) { - dispatch({ - type: types.FETCH_CHANNEL_CLAIMS_STARTED, - data: { uri } - }) + return function(dispatch, getState) { + dispatch({ + type: types.FETCH_CHANNEL_CLAIMS_STARTED, + data: { uri } + }); - lbry.resolve({ uri }).then((resolutionInfo) => { - const { - claims_in_channel, - } = resolutionInfo ? resolutionInfo : { claims_in_channel: [] } + lbry.resolve({ uri }).then(resolutionInfo => { + const { claims_in_channel } = resolutionInfo + ? resolutionInfo + : { claims_in_channel: [] }; - dispatch({ - type: types.FETCH_CHANNEL_CLAIMS_COMPLETED, - data: { - uri, - claims: claims_in_channel - } - }) - }) - } + dispatch({ + type: types.FETCH_CHANNEL_CLAIMS_COMPLETED, + data: { + uri, + claims: claims_in_channel + } + }); + }); + }; } export function doFetchClaimListMine() { - return function(dispatch, getState) { - dispatch({ - type: types.FETCH_CLAIM_LIST_MINE_STARTED - }) + return function(dispatch, getState) { + dispatch({ + type: types.FETCH_CLAIM_LIST_MINE_STARTED + }); - - lbry.claim_list_mine().then((claims) => { - dispatch({ - type: types.FETCH_CLAIM_LIST_MINE_COMPLETED, - data: { - claims - } - }) - }) - } -} \ No newline at end of file + lbry.claim_list_mine().then(claims => { + dispatch({ + type: types.FETCH_CLAIM_LIST_MINE_COMPLETED, + data: { + claims + } + }); + }); + }; +} diff --git a/ui/js/actions/cost_info.js b/ui/js/actions/cost_info.js index dbad86f33..d1f1e60c3 100644 --- a/ui/js/actions/cost_info.js +++ b/ui/js/actions/cost_info.js @@ -1,77 +1,68 @@ - import * as types from 'constants/action_types' -import lbry from 'lbry' -import lbryio from 'lbryio' -import { - doResolveUri -} from 'actions/content' -import { - selectResolvingUris, -} from 'selectors/content' -import { - selectClaimsByUri -} from 'selectors/claims' -import { - selectSettingsIsGenerous -} from 'selectors/settings' +import * as types from 'constants/action_types'; +import lbry from 'lbry'; +import lbryio from 'lbryio'; +import { doResolveUri } from 'actions/content'; +import { selectResolvingUris } from 'selectors/content'; +import { selectClaimsByUri } from 'selectors/claims'; +import { selectSettingsIsGenerous } from 'selectors/settings'; export function doFetchCostInfoForUri(uri) { - return function(dispatch, getState) { - const state = getState(), - claim = selectClaimsByUri(state)[uri], - isResolving = selectResolvingUris(state).indexOf(uri) !== -1, - isGenerous = selectSettingsIsGenerous(state) + return function(dispatch, getState) { + const state = getState(), + claim = selectClaimsByUri(state)[uri], + isResolving = selectResolvingUris(state).indexOf(uri) !== -1, + isGenerous = selectSettingsIsGenerous(state); - if (claim === null) { //claim doesn't exist, nothing to fetch a cost for - return - } + if (claim === null) { + //claim doesn't exist, nothing to fetch a cost for + return; + } - if (!claim) { - setTimeout(() => { - dispatch(doFetchCostInfoForUri(uri)) - }, 1000) - if (!isResolving) { - dispatch(doResolveUri(uri)) - } - return - } + if (!claim) { + setTimeout(() => { + dispatch(doFetchCostInfoForUri(uri)); + }, 1000); + if (!isResolving) { + dispatch(doResolveUri(uri)); + } + return; + } + function begin() { + dispatch({ + type: types.FETCH_COST_INFO_STARTED, + data: { + uri + } + }); + } - function begin() { - dispatch({ - type: types.FETCH_COST_INFO_STARTED, - data: { - uri, - } - }) - } + function resolve(costInfo) { + dispatch({ + type: types.FETCH_COST_INFO_COMPLETED, + data: { + uri, + costInfo + } + }); + } - function resolve(costInfo) { - dispatch({ - type: types.FETCH_COST_INFO_COMPLETED, - data: { - uri, - costInfo, - } - }) - } - - if (isGenerous && claim) { - let cost - const fee = claim.value.stream.metadata.fee; - if (fee === undefined ) { - resolve({ cost: 0, includesData: true }) - } else if (fee.currency == 'LBC') { - resolve({ cost: fee.amount, includesData: true }) - } else { - begin() - lbryio.getExchangeRates().then(({lbc_usd}) => { - resolve({ cost: fee.amount / lbc_usd, includesData: true }) - }); - } - } else { - begin() - lbry.getCostInfo(uri).then(resolve) - } - } + if (isGenerous && claim) { + let cost; + const fee = claim.value.stream.metadata.fee; + if (fee === undefined) { + resolve({ cost: 0, includesData: true }); + } else if (fee.currency == 'LBC') { + resolve({ cost: fee.amount, includesData: true }); + } else { + begin(); + lbryio.getExchangeRates().then(({ lbc_usd }) => { + resolve({ cost: fee.amount / lbc_usd, includesData: true }); + }); + } + } else { + begin(); + lbry.getCostInfo(uri).then(resolve); + } + }; } - diff --git a/ui/js/actions/file_info.js b/ui/js/actions/file_info.js index 44d76885c..18b438015 100644 --- a/ui/js/actions/file_info.js +++ b/ui/js/actions/file_info.js @@ -1,121 +1,113 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' +import * as types from 'constants/action_types'; +import lbry from 'lbry'; +import { doFetchClaimListMine } from 'actions/content'; import { - doFetchClaimListMine -} from 'actions/content' + selectClaimsByUri, + selectClaimListMineIsPending +} from 'selectors/claims'; import { - selectClaimsByUri, - selectClaimListMineIsPending, -} from 'selectors/claims' -import { - selectFileListIsPending, - selectAllFileInfos, - selectUrisLoading, -} from 'selectors/file_info' -import { - doCloseModal, -} from 'actions/app' + selectFileListIsPending, + selectAllFileInfos, + selectUrisLoading +} from 'selectors/file_info'; +import { doCloseModal } from 'actions/app'; -const { - shell, -} = require('electron') +const { shell } = require('electron'); export function doFetchFileInfo(uri) { - return function(dispatch, getState) { - const state = getState() - const claim = selectClaimsByUri(state)[uri] - const outpoint = claim ? `${claim.txid}:${claim.nout}` : null - const alreadyFetching = !!selectUrisLoading(state)[uri] + return function(dispatch, getState) { + const state = getState(); + const claim = selectClaimsByUri(state)[uri]; + const outpoint = claim ? `${claim.txid}:${claim.nout}` : null; + const alreadyFetching = !!selectUrisLoading(state)[uri]; - if (!alreadyFetching) { - dispatch({ - type: types.FETCH_FILE_INFO_STARTED, - data: { - outpoint, - } - }) + if (!alreadyFetching) { + dispatch({ + type: types.FETCH_FILE_INFO_STARTED, + data: { + outpoint + } + }); - lbry.file_list({outpoint: outpoint, full_status: true}).then(fileInfos => { - - dispatch({ - type: types.FETCH_FILE_INFO_COMPLETED, - data: { - outpoint, - fileInfo: fileInfos && fileInfos.length ? fileInfos[0] : null, - } - }) - }) - } - } + lbry + .file_list({ outpoint: outpoint, full_status: true }) + .then(fileInfos => { + dispatch({ + type: types.FETCH_FILE_INFO_COMPLETED, + data: { + outpoint, + fileInfo: fileInfos && fileInfos.length ? fileInfos[0] : null + } + }); + }); + } + }; } export function doFileList() { - return function(dispatch, getState) { - const state = getState() - const isPending = selectFileListIsPending(state) + return function(dispatch, getState) { + const state = getState(); + const isPending = selectFileListIsPending(state); - if (!isPending) { - dispatch({ - type: types.FILE_LIST_STARTED, - }) + if (!isPending) { + dispatch({ + type: types.FILE_LIST_STARTED + }); - lbry.file_list().then((fileInfos) => { - dispatch({ - type: types.FILE_LIST_COMPLETED, - data: { - fileInfos, - } - }) - }) - } - } + lbry.file_list().then(fileInfos => { + dispatch({ + type: types.FILE_LIST_COMPLETED, + data: { + fileInfos + } + }); + }); + } + }; } export function doOpenFileInShell(fileInfo) { - return function(dispatch, getState) { - shell.openItem(fileInfo.download_path) - } + return function(dispatch, getState) { + shell.openItem(fileInfo.download_path); + }; } export function doOpenFileInFolder(fileInfo) { - return function(dispatch, getState) { - shell.showItemInFolder(fileInfo.download_path) - } + return function(dispatch, getState) { + shell.showItemInFolder(fileInfo.download_path); + }; } export function doDeleteFile(outpoint, deleteFromComputer) { - return function(dispatch, getState) { + return function(dispatch, getState) { + dispatch({ + type: types.FILE_DELETE, + data: { + outpoint + } + }); - dispatch({ - type: types.FILE_DELETE, - data: { - outpoint - } - }) + lbry.file_delete({ + outpoint: outpoint, + delete_target_file: deleteFromComputer + }); - lbry.file_delete({ - outpoint: outpoint, - delete_target_file: deleteFromComputer, - }) - - dispatch(doCloseModal()) - } + dispatch(doCloseModal()); + }; } - export function doFetchFileInfosAndPublishedClaims() { - return function(dispatch, getState) { - const state = getState(), - isClaimListMinePending = selectClaimListMineIsPending(state), - isFileInfoListPending = selectFileListIsPending(state) + return function(dispatch, getState) { + const state = getState(), + isClaimListMinePending = selectClaimListMineIsPending(state), + isFileInfoListPending = selectFileListIsPending(state); - if (isClaimListMinePending === undefined) { - dispatch(doFetchClaimListMine()) - } + if (isClaimListMinePending === undefined) { + dispatch(doFetchClaimListMine()); + } - if (isFileInfoListPending === undefined) { - dispatch(doFileList()) - } - } + if (isFileInfoListPending === undefined) { + dispatch(doFileList()); + } + }; } - diff --git a/ui/js/actions/rewards.js b/ui/js/actions/rewards.js index 84f65047f..588c9c117 100644 --- a/ui/js/actions/rewards.js +++ b/ui/js/actions/rewards.js @@ -1,36 +1,35 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' +import * as types from 'constants/action_types'; +import lbry from 'lbry'; import lbryio from 'lbryio'; -import rewards from 'rewards' +import rewards from 'rewards'; export function doFetchRewards() { - return function(dispatch, getState) { - const state = getState() + return function(dispatch, getState) { + const state = getState(); - dispatch({ - type: types.FETCH_REWARDS_STARTED, - }) + dispatch({ + type: types.FETCH_REWARDS_STARTED + }); - lbryio.call('reward', 'list', {}).then(function(userRewards) { - dispatch({ - type: types.FETCH_REWARDS_COMPLETED, - data: { userRewards } - }) - }); - } + lbryio.call('reward', 'list', {}).then(function(userRewards) { + dispatch({ + type: types.FETCH_REWARDS_COMPLETED, + data: { userRewards } + }); + }); + }; } export function doClaimReward(rewardType) { - return function(dispatch, getState) { - try { - rewards.claimReward(rewards[rewardType]) - dispatch({ - type: types.REWARD_CLAIMED, - data: { - reward: rewards[rewardType] - } - }) - } catch(err) { - } - } + return function(dispatch, getState) { + try { + rewards.claimReward(rewards[rewardType]); + dispatch({ + type: types.REWARD_CLAIMED, + data: { + reward: rewards[rewardType] + } + }); + } catch (err) {} + }; } diff --git a/ui/js/actions/search.js b/ui/js/actions/search.js index 149aa78ea..9c4e8f00c 100644 --- a/ui/js/actions/search.js +++ b/ui/js/actions/search.js @@ -1,54 +1,47 @@ -import * as types from 'constants/action_types' -import lbryuri from 'lbryuri' -import lighthouse from 'lighthouse' -import { - doResolveUri, -} from 'actions/content' -import { - doNavigate, - doHistoryPush -} from 'actions/app' -import { - selectCurrentPage, -} from 'selectors/app' +import * as types from 'constants/action_types'; +import lbryuri from 'lbryuri'; +import lighthouse from 'lighthouse'; +import { doResolveUri } from 'actions/content'; +import { doNavigate, doHistoryPush } from 'actions/app'; +import { selectCurrentPage } from 'selectors/app'; export function doSearch(query) { - return function(dispatch, getState) { - const state = getState() - const page = selectCurrentPage(state) + return function(dispatch, getState) { + const state = getState(); + const page = selectCurrentPage(state); - if (!query) { - return dispatch({ - type: types.SEARCH_CANCELLED, - }) - } + if (!query) { + return dispatch({ + type: types.SEARCH_CANCELLED + }); + } - dispatch({ - type: types.SEARCH_STARTED, - data: { query } - }) + dispatch({ + type: types.SEARCH_STARTED, + data: { query } + }); - if(page != 'search') { - dispatch(doNavigate('search', { query: query })) - } else { - 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)) - }) + if (page != 'search') { + dispatch(doNavigate('search', { query: query })); + } else { + 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, - } - }) - }) - } - } + dispatch({ + type: types.SEARCH_COMPLETED, + data: { + query, + results + } + }); + }); + } + }; } diff --git a/ui/js/actions/settings.js b/ui/js/actions/settings.js index a0742d377..714b3b676 100644 --- a/ui/js/actions/settings.js +++ b/ui/js/actions/settings.js @@ -1,31 +1,31 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' +import * as types from 'constants/action_types'; +import lbry from 'lbry'; export function doFetchDaemonSettings() { - return function(dispatch, getState) { - lbry.settings_get().then((settings) => { - dispatch({ - type: types.DAEMON_SETTINGS_RECEIVED, - data: { - settings - } - }) - }) - } + return function(dispatch, getState) { + lbry.settings_get().then(settings => { + dispatch({ + type: types.DAEMON_SETTINGS_RECEIVED, + data: { + settings + } + }); + }); + }; } export function doSetDaemonSetting(key, value) { - return function(dispatch, getState) { - let settings = {}; - settings[key] = value; - lbry.settings_set(settings).then(settings) - lbry.settings_get().then((settings) => { - dispatch({ - type: types.DAEMON_SETTINGS_RECEIVED, - data: { - settings - } - }) - }) - } -} \ No newline at end of file + return function(dispatch, getState) { + let settings = {}; + settings[key] = value; + lbry.settings_set(settings).then(settings); + lbry.settings_get().then(settings => { + dispatch({ + type: types.DAEMON_SETTINGS_RECEIVED, + data: { + settings + } + }); + }); + }; +} diff --git a/ui/js/actions/wallet.js b/ui/js/actions/wallet.js index 53eccfa67..5b5e941ec 100644 --- a/ui/js/actions/wallet.js +++ b/ui/js/actions/wallet.js @@ -1,125 +1,127 @@ -import * as types from 'constants/action_types' -import lbry from 'lbry' +import * as types from 'constants/action_types'; +import lbry from 'lbry'; import { - selectDraftTransaction, - selectDraftTransactionAmount, - selectBalance, -} from 'selectors/wallet' -import { - doOpenModal, -} from 'actions/app' + selectDraftTransaction, + selectDraftTransactionAmount, + selectBalance +} from 'selectors/wallet'; +import { doOpenModal } from 'actions/app'; export function doUpdateBalance(balance) { - return { - type: types.UPDATE_BALANCE, - data: { - balance: balance - } - } + return { + type: types.UPDATE_BALANCE, + data: { + balance: balance + } + }; } export function doFetchTransactions() { - return function(dispatch, getState) { - dispatch({ - type: types.FETCH_TRANSACTIONS_STARTED - }) + return function(dispatch, getState) { + dispatch({ + type: types.FETCH_TRANSACTIONS_STARTED + }); - lbry.call('transaction_list', {}, (results) => { - dispatch({ - type: types.FETCH_TRANSACTIONS_COMPLETED, - data: { - transactions: results - } - }) - }) - } + lbry.call('transaction_list', {}, results => { + dispatch({ + type: types.FETCH_TRANSACTIONS_COMPLETED, + data: { + transactions: results + } + }); + }); + }; } export function doGetNewAddress() { - return function(dispatch, getState) { - dispatch({ - type: types.GET_NEW_ADDRESS_STARTED - }) + return function(dispatch, getState) { + dispatch({ + type: types.GET_NEW_ADDRESS_STARTED + }); - lbry.wallet_new_address().then(function(address) { - localStorage.setItem('wallet_address', address); - dispatch({ - type: types.GET_NEW_ADDRESS_COMPLETED, - data: { address } - }) - }) - } + lbry.wallet_new_address().then(function(address) { + localStorage.setItem('wallet_address', address); + dispatch({ + type: types.GET_NEW_ADDRESS_COMPLETED, + data: { address } + }); + }); + }; } export function doCheckAddressIsMine(address) { - return function(dispatch, getState) { - dispatch({ - type: types.CHECK_ADDRESS_IS_MINE_STARTED - }) + return function(dispatch, getState) { + dispatch({ + type: types.CHECK_ADDRESS_IS_MINE_STARTED + }); - lbry.checkAddressIsMine(address, (isMine) => { - if (!isMine) dispatch(doGetNewAddress()) + lbry.checkAddressIsMine(address, isMine => { + if (!isMine) dispatch(doGetNewAddress()); - dispatch({ - type: types.CHECK_ADDRESS_IS_MINE_COMPLETED - }) - }) - } + dispatch({ + type: types.CHECK_ADDRESS_IS_MINE_COMPLETED + }); + }); + }; } export function doSendDraftTransaction() { - return function(dispatch, getState) { - const state = getState() - const draftTx = selectDraftTransaction(state) - const balance = selectBalance(state) - const amount = selectDraftTransactionAmount(state) + return function(dispatch, getState) { + const state = getState(); + const draftTx = selectDraftTransaction(state); + const balance = selectBalance(state); + const amount = selectDraftTransactionAmount(state); - if (balance - amount < 1) { - return dispatch(doOpenModal('insufficientBalance')) - } + if (balance - amount < 1) { + return dispatch(doOpenModal('insufficientBalance')); + } - dispatch({ - type: types.SEND_TRANSACTION_STARTED, - }) + dispatch({ + type: types.SEND_TRANSACTION_STARTED + }); - const successCallback = (results) => { - if(results === true) { - dispatch({ - type: types.SEND_TRANSACTION_COMPLETED, - }) - dispatch(doOpenModal('transactionSuccessful')) - } - else { - dispatch({ - type: types.SEND_TRANSACTION_FAILED, - data: { error: results } - }) - dispatch(doOpenModal('transactionFailed')) - } - } + const successCallback = results => { + if (results === true) { + dispatch({ + type: types.SEND_TRANSACTION_COMPLETED + }); + dispatch(doOpenModal('transactionSuccessful')); + } else { + dispatch({ + type: types.SEND_TRANSACTION_FAILED, + data: { error: results } + }); + dispatch(doOpenModal('transactionFailed')); + } + }; - const errorCallback = (error) => { - dispatch({ - type: types.SEND_TRANSACTION_FAILED, - data: { error: error.message } - }) - dispatch(doOpenModal('transactionFailed')) - } + const errorCallback = error => { + dispatch({ + type: types.SEND_TRANSACTION_FAILED, + data: { error: error.message } + }); + dispatch(doOpenModal('transactionFailed')); + }; - lbry.sendToAddress(draftTx.amount, draftTx.address, successCallback, errorCallback); - } + lbry.sendToAddress( + draftTx.amount, + draftTx.address, + successCallback, + errorCallback + ); + }; } export function doSetDraftTransactionAmount(amount) { - return { - type: types.SET_DRAFT_TRANSACTION_AMOUNT, - data: { amount } - } + return { + type: types.SET_DRAFT_TRANSACTION_AMOUNT, + data: { amount } + }; } export function doSetDraftTransactionAddress(address) { - return { - type: types.SET_DRAFT_TRANSACTION_ADDRESS, - data: { address } - } + return { + type: types.SET_DRAFT_TRANSACTION_ADDRESS, + data: { address } + }; } diff --git a/ui/js/app.js b/ui/js/app.js index 2f94dc302..1f1f32ecd 100644 --- a/ui/js/app.js +++ b/ui/js/app.js @@ -3,20 +3,26 @@ import lbry from './lbry.js'; const env = ENV; const config = require(`./config/${env}`); -const language = lbry.getClientSetting('language') ? lbry.getClientSetting('language') : 'en'; -const i18n = require('y18n')({directory: 'app/locales', updateFiles: false, locale: language}); +const language = lbry.getClientSetting('language') + ? lbry.getClientSetting('language') + : 'en'; +const i18n = require('y18n')({ + directory: 'app/locales', + updateFiles: false, + locale: language +}); const logs = []; const app = { - env: env, - config: config, - store: store, - i18n: i18n, - logs: logs, - log: function(message) { - console.log(message); - logs.push(message); - } -} + env: env, + config: config, + store: store, + i18n: i18n, + logs: logs, + log: function(message) { + console.log(message); + logs.push(message); + } +}; window.__ = i18n.__; window.__n = i18n.__n; diff --git a/ui/js/component/app/index.js b/ui/js/component/app/index.js index 5de84e28f..cb67dccd7 100644 --- a/ui/js/component/app/index.js +++ b/ui/js/component/app/index.js @@ -1,26 +1,19 @@ import React from 'react'; -import { connect } from 'react-redux' +import { connect } from 'react-redux'; -import { - selectCurrentModal, -} from 'selectors/app' -import { - doCheckUpgradeAvailable, - doAlertError, -} from 'actions/app' -import { - doUpdateBalance, -} from 'actions/wallet' -import App from './view' +import { selectCurrentModal } from 'selectors/app'; +import { doCheckUpgradeAvailable, doAlertError } from 'actions/app'; +import { doUpdateBalance } from 'actions/wallet'; +import App from './view'; -const select = (state) => ({ - modal: selectCurrentModal(state), -}) +const select = state => ({ + modal: selectCurrentModal(state) +}); -const perform = (dispatch) => ({ - alertError: (errorList) => dispatch(doAlertError(errorList)), - checkUpgradeAvailable: () => dispatch(doCheckUpgradeAvailable()), - updateBalance: (balance) => dispatch(doUpdateBalance(balance)) -}) +const perform = dispatch => ({ + alertError: errorList => dispatch(doAlertError(errorList)), + checkUpgradeAvailable: () => dispatch(doCheckUpgradeAvailable()), + updateBalance: balance => dispatch(doUpdateBalance(balance)) +}); -export default connect(select, perform)(App) +export default connect(select, perform)(App); diff --git a/ui/js/component/app/view.jsx b/ui/js/component/app/view.jsx index 1c7ff4eb4..1c8b2ec1c 100644 --- a/ui/js/component/app/view.jsx +++ b/ui/js/component/app/view.jsx @@ -1,42 +1,42 @@ -import React from 'react' -import Router from 'component/router' +import React from 'react'; +import Router from 'component/router'; import Header from 'component/header'; -import ErrorModal from 'component/errorModal' -import DownloadingModal from 'component/downloadingModal' -import UpgradeModal from 'component/upgradeModal' -import lbry from 'lbry' -import {Line} from 'rc-progress' +import ErrorModal from 'component/errorModal'; +import DownloadingModal from 'component/downloadingModal'; +import UpgradeModal from 'component/upgradeModal'; +import lbry from 'lbry'; +import { Line } from 'rc-progress'; class App extends React.Component { - componentWillMount() { - document.addEventListener('unhandledError', (event) => { - this.props.alertError(event.detail); - }); + componentWillMount() { + document.addEventListener('unhandledError', event => { + this.props.alertError(event.detail); + }); - if (!this.props.upgradeSkipped) { - this.props.checkUpgradeAvailable() - } + if (!this.props.upgradeSkipped) { + this.props.checkUpgradeAvailable(); + } - lbry.balanceSubscribe((balance) => { - this.props.updateBalance(balance) - }) - } + lbry.balanceSubscribe(balance => { + this.props.updateBalance(balance); + }); + } - render() { - const { - modal, - } = this.props + render() { + const { modal } = this.props; - return
-
-
- -
- {modal == 'upgrade' && } - {modal == 'downloading' && } - {modal == 'error' && } -
- } + return ( +
+
+
+ +
+ {modal == 'upgrade' && } + {modal == 'downloading' && } + {modal == 'error' && } +
+ ); + } } -export default App +export default App; diff --git a/ui/js/component/auth.js b/ui/js/component/auth.js index 8bea57b38..579ad46eb 100644 --- a/ui/js/component/auth.js +++ b/ui/js/component/auth.js @@ -1,327 +1,517 @@ -import React from "react"; -import lbry from "../lbry.js"; -import lbryio from "../lbryio.js"; -import Modal from "./modal.js"; -import ModalPage from "./modal-page.js"; -import Link from "component/link" -import {RewardLink} from 'component/reward-link'; -import {FormRow} from "../component/form.js"; -import {CreditAmount, Address} from "../component/common.js"; -import {getLocal, setLocal} from '../utils.js'; -import rewards from '../rewards' - +import React from 'react'; +import lbry from '../lbry.js'; +import lbryio from '../lbryio.js'; +import Modal from './modal.js'; +import ModalPage from './modal-page.js'; +import Link from 'component/link'; +import { RewardLink } from 'component/reward-link'; +import { FormRow } from '../component/form.js'; +import { CreditAmount, Address } from '../component/common.js'; +import { getLocal, setLocal } from '../utils.js'; +import rewards from '../rewards'; class SubmitEmailStage extends React.Component { - constructor(props) { - super(props); + constructor(props) { + super(props); - this.state = { - rewardType: null, - email: '', - submitting: false - }; - } + this.state = { + rewardType: null, + email: '', + submitting: false + }; + } - handleEmailChanged(event) { - this.setState({ - email: event.target.value, - }); - } + handleEmailChanged(event) { + this.setState({ + email: event.target.value + }); + } - onEmailSaved(email) { - this.props.setStage("confirm", { email: email }) - } + onEmailSaved(email) { + this.props.setStage('confirm', { email: email }); + } - handleSubmit(event) { - event.preventDefault(); + handleSubmit(event) { + event.preventDefault(); - this.setState({ - submitting: true, - }); - lbryio.call('user_email', 'new', {email: this.state.email}, 'post').then(() => { - this.onEmailSaved(this.state.email); - }, (error) => { - if (error.xhr && (error.xhr.status == 409 || error.message == __("This email is already in use"))) { - this.onEmailSaved(this.state.email); - return; - } else if (this._emailRow) { - this._emailRow.showError(error.message) - } - this.setState({ submitting: false }); - }); - } + this.setState({ + submitting: true + }); + lbryio.call('user_email', 'new', { email: this.state.email }, 'post').then( + () => { + this.onEmailSaved(this.state.email); + }, + error => { + if ( + error.xhr && + (error.xhr.status == 409 || + error.message == __('This email is already in use')) + ) { + this.onEmailSaved(this.state.email); + return; + } else if (this._emailRow) { + this._emailRow.showError(error.message); + } + this.setState({ submitting: false }); + } + ); + } - render() { - return ( -
-
{ this.handleSubmit(event) }}> - { this._emailRow = ref }} type="text" label={__("Email")} placeholder="scrwvwls@lbry.io" - name="email" value={this.state.email} - onChange={(event) => { this.handleEmailChanged(event) }} /> -
- { this.handleSubmit(event) }} /> -
- -
- ); - } + render() { + return ( +
+
{ + this.handleSubmit(event); + }} + > + { + this._emailRow = ref; + }} + type="text" + label={__('Email')} + placeholder="scrwvwls@lbry.io" + name="email" + value={this.state.email} + onChange={event => { + this.handleEmailChanged(event); + }} + /> +
+ { + this.handleSubmit(event); + }} + /> +
+ +
+ ); + } } class ConfirmEmailStage extends React.Component { - constructor(props) { - super(props); + constructor(props) { + super(props); - this.state = { - rewardType: null, - code: '', - submitting: false, - errorMessage: null, - }; - } + this.state = { + rewardType: null, + code: '', + submitting: false, + errorMessage: null + }; + } - handleCodeChanged(event) { - this.setState({ - code: event.target.value, - }); - } + handleCodeChanged(event) { + this.setState({ + code: event.target.value + }); + } - handleSubmit(event) { - event.preventDefault(); - this.setState({ - submitting: true, - }); + handleSubmit(event) { + event.preventDefault(); + this.setState({ + submitting: true + }); - const onSubmitError = (error) => { - if (this._codeRow) { - this._codeRow.showError(error.message) - } - this.setState({ submitting: false }); - }; + const onSubmitError = error => { + if (this._codeRow) { + this._codeRow.showError(error.message); + } + this.setState({ submitting: false }); + }; - lbryio.call('user_email', 'confirm', {verification_token: this.state.code, email: this.props.email}, 'post').then((userEmail) => { - if (userEmail.is_verified) { - this.props.setStage("welcome") - } else { - onSubmitError(new Error(__("Your email is still not verified."))) //shouldn't happen? - } - }, onSubmitError); - } + lbryio + .call( + 'user_email', + 'confirm', + { verification_token: this.state.code, email: this.props.email }, + 'post' + ) + .then(userEmail => { + if (userEmail.is_verified) { + this.props.setStage('welcome'); + } else { + onSubmitError(new Error(__('Your email is still not verified.'))); //shouldn't happen? + } + }, onSubmitError); + } - render() { - return ( -
-
{ this.handleSubmit(event) }}> - { this._codeRow = ref }} type="text" - name="code" placeholder="a94bXXXXXXXXXXXXXX" value={this.state.code} onChange={(event) => { this.handleCodeChanged(event) }} - helper={__("A verification code is required to access this version.")}/> -
- { this.handleSubmit(event)}} /> -
-
- {__("No code?")} { this.props.setStage("nocode")}} label={__("Click here")} />. -
- -
- ); - } + render() { + return ( +
+
{ + this.handleSubmit(event); + }} + > + { + this._codeRow = ref; + }} + type="text" + name="code" + placeholder="a94bXXXXXXXXXXXXXX" + value={this.state.code} + onChange={event => { + this.handleCodeChanged(event); + }} + helper={__( + 'A verification code is required to access this version.' + )} + /> +
+ { + this.handleSubmit(event); + }} + /> +
+
+ {__('No code?')} + {' '} + { + this.props.setStage('nocode'); + }} + label={__('Click here')} + />. +
+ +
+ ); + } } class WelcomeStage extends React.Component { - static propTypes = { - endAuth: React.PropTypes.func, - } + static propTypes = { + endAuth: React.PropTypes.func + }; - constructor(props) { - super(props); + constructor(props) { + super(props); - this.state = { - hasReward: false, - rewardAmount: null, - }; - } + this.state = { + hasReward: false, + rewardAmount: null + }; + } - onRewardClaim(reward) { - this.setState({ - hasReward: true, - rewardAmount: reward.amount - }) - } + onRewardClaim(reward) { + this.setState({ + hasReward: true, + rewardAmount: reward.amount + }); + } - render() { - return ( - !this.state.hasReward ? - -
-

{__("Welcome to LBRY.")}

-

{__("Using LBRY is like dating a centaur. Totally normal up top, and way different underneath.")}

-

{__("Up top, LBRY is similar to popular media sites.")}

-

{__("Below, LBRY is controlled by users -- you -- via blockchain and decentralization.")}

-

{__("Thank you for making content freedom possible! Here's a nickel, kid.")}

-
- { this.onRewardClaim(event) }} onRewardFailure={() => this.props.setStage(null)} onConfirmed={() => { this.props.setStage(null) }} /> -
-
-
: - { this.props.setStage(null) }}> -
-

{__("About Your Reward")}

-

{__("You earned a reward of ")} {__("LBRY credits, or \"LBC\".")}

-

{__("This reward will show in your Wallet momentarily, probably while you are reading this message.")}

-

{__("LBC is used to compensate creators, to publish, and to have say in how the network works.")}

-

{__("No need to understand it all just yet! Try watching or downloading something next.")}

-

{__("Finally, know that LBRY is an early beta and that it earns the name.")}

-
-
- ); - } + render() { + return !this.state.hasReward + ? +
+

{__('Welcome to LBRY.')}

+

+ {__( + 'Using LBRY is like dating a centaur. Totally normal up top, and way different underneath.' + )} +

+

{__('Up top, LBRY is similar to popular media sites.')}

+

+ {__( + 'Below, LBRY is controlled by users -- you -- via blockchain and decentralization.' + )} +

+

+ {__( + "Thank you for making content freedom possible! Here's a nickel, kid." + )} +

+
+ { + this.onRewardClaim(event); + }} + onRewardFailure={() => this.props.setStage(null)} + onConfirmed={() => { + this.props.setStage(null); + }} + /> +
+
+
+ : { + this.props.setStage(null); + }} + > +
+

{__('About Your Reward')}

+

+ {__('You earned a reward of ')} + {' '} + {' '}{__('LBRY credits, or "LBC".')} +

+

+ {__( + 'This reward will show in your Wallet momentarily, probably while you are reading this message.' + )} +

+

+ {__( + 'LBC is used to compensate creators, to publish, and to have say in how the network works.' + )} +

+

+ {__( + 'No need to understand it all just yet! Try watching or downloading something next.' + )} +

+

+ {__( + 'Finally, know that LBRY is an early beta and that it earns the name.' + )} +

+
+
; + } } -const ErrorStage = (props) => { - return
-

{__("An error was encountered that we cannot continue from.")}

-

{__("At least we're earning the name beta.")}

- { props.errorText ?

{__("Message:")} {props.errorText}

: '' } - { window.location.reload() } } /> -
-} - -const PendingStage = (props) => { - return
-

{__("Preparing for first access")}

-
-} +const ErrorStage = props => { + return ( +
+

{__('An error was encountered that we cannot continue from.')}

+

{__("At least we're earning the name beta.")}

+ {props.errorText ?

{__('Message:')} {props.errorText}

: ''} + { + window.location.reload(); + }} + /> +
+ ); +}; +const PendingStage = props => { + return ( +
+

+ {__('Preparing for first access')} +

+
+ ); +}; class CodeRequiredStage extends React.Component { - constructor(props) { - super(props); + constructor(props) { + super(props); - this._balanceSubscribeId = null + this._balanceSubscribeId = null; - this.state = { - balance: 0, - address: getLocal('wallet_address') - }; - } + this.state = { + balance: 0, + address: getLocal('wallet_address') + }; + } - componentWillMount() { - this._balanceSubscribeId = lbry.balanceSubscribe((balance) => { - this.setState({ - balance: balance - }); - }) + componentWillMount() { + this._balanceSubscribeId = lbry.balanceSubscribe(balance => { + this.setState({ + balance: balance + }); + }); - if (!this.state.address) { - lbry.wallet_unused_address().then((address) => { - setLocal('wallet_address', address); - this.setState({ address: address }); - }); - } - } + if (!this.state.address) { + lbry.wallet_unused_address().then(address => { + setLocal('wallet_address', address); + this.setState({ address: address }); + }); + } + } - componentWillUnmount() { - if (this._balanceSubscribeId) { - lbry.balanceUnsubscribe(this._balanceSubscribeId) - } - } + componentWillUnmount() { + if (this._balanceSubscribeId) { + lbry.balanceUnsubscribe(this._balanceSubscribeId); + } + } - render() { - const disabled = this.state.balance < 1; - return ( -
-
-

{__("Access to LBRY is restricted as we build and scale the network.")}

-

{__("There are two ways in:")}

-

{__("Own LBRY Credits")}

-

{__("If you own at least 1 LBC, you can get in right now.")}

-

{ setLocal('auth_bypassed', true); this.props.setStage(null); }} - disabled={disabled} label={__("Let Me In")} button={ disabled ? "alt" : "primary" } />

-

{__("Your balance is ")}. {__("To increase your balance, send credits to this address:")}

-

-

{__("If you don't understand how to send credits, then...")}

-
-
-

{__("Wait For A Code")}

-

{__("If you provide your email, you'll automatically receive a notification when the system is open.")}

-

{ this.props.setStage("email"); }} label={__("Return")} />

-
-
- ); - } + render() { + const disabled = this.state.balance < 1; + return ( +
+
+

+ {__( + 'Access to LBRY is restricted as we build and scale the network.' + )} +

+

{__('There are two ways in:')}

+

{__('Own LBRY Credits')}

+

{__('If you own at least 1 LBC, you can get in right now.')}

+

+ { + setLocal('auth_bypassed', true); + this.props.setStage(null); + }} + disabled={disabled} + label={__('Let Me In')} + button={disabled ? 'alt' : 'primary'} + /> +

+

+ {__('Your balance is ')}. {__('To increase your balance, send credits to this address:')} +

+

+

+

+

{__("If you don't understand how to send credits, then...")}

+
+
+

{__('Wait For A Code')}

+

+ {__( + "If you provide your email, you'll automatically receive a notification when the system is open." + )} +

+

+ { + this.props.setStage('email'); + }} + label={__('Return')} + /> +

+
+
+ ); + } } - export class AuthOverlay extends React.Component { - constructor(props) { - super(props); + constructor(props) { + super(props); - this._stages = { - pending: PendingStage, - error: ErrorStage, - nocode: CodeRequiredStage, - email: SubmitEmailStage, - confirm: ConfirmEmailStage, - welcome: WelcomeStage - } + this._stages = { + pending: PendingStage, + error: ErrorStage, + nocode: CodeRequiredStage, + email: SubmitEmailStage, + confirm: ConfirmEmailStage, + welcome: WelcomeStage + }; - this.state = { - stage: "pending", - stageProps: {} - }; - } + this.state = { + stage: 'pending', + stageProps: {} + }; + } - setStage(stage, stageProps = {}) { - this.setState({ - stage: stage, - stageProps: stageProps - }) - } + setStage(stage, stageProps = {}) { + this.setState({ + stage: stage, + stageProps: stageProps + }); + } - componentWillMount() { - lbryio.authenticate().then((user) => { - if (!user.has_verified_email) { - if (getLocal('auth_bypassed')) { - this.setStage(null) - } else { - this.setStage("email", {}) - } - } else { - lbryio.call('reward', 'list', {}).then((userRewards) => { - userRewards.filter(function(reward) { - return reward.reward_type == rewards.TYPE_NEW_USER && reward.transaction_id; - }).length ? - this.setStage(null) : - this.setStage("welcome") - }); - } - }).catch((err) => { - this.setStage("error", { errorText: err.message }) - document.dispatchEvent(new CustomEvent('unhandledError', { - detail: { - message: err.message, - data: err.stack - } - })); - }) - } + componentWillMount() { + lbryio + .authenticate() + .then(user => { + if (!user.has_verified_email) { + if (getLocal('auth_bypassed')) { + this.setStage(null); + } else { + this.setStage('email', {}); + } + } else { + lbryio.call('reward', 'list', {}).then(userRewards => { + userRewards.filter(function(reward) { + return ( + reward.reward_type == rewards.TYPE_NEW_USER && + reward.transaction_id + ); + }).length + ? this.setStage(null) + : this.setStage('welcome'); + }); + } + }) + .catch(err => { + this.setStage('error', { errorText: err.message }); + document.dispatchEvent( + new CustomEvent('unhandledError', { + detail: { + message: err.message, + data: err.stack + } + }) + ); + }); + } - render() { - if (!this.state.stage) { - return null; - } - const StageContent = this._stages[this.state.stage]; + render() { + if (!this.state.stage) { + return null; + } + const StageContent = this._stages[this.state.stage]; - if (!StageContent) { - return {__("Unknown authentication step.")} - } + if (!StageContent) { + return ( + {__('Unknown authentication step.')} + ); + } - return ( - this.state.stage != "welcome" ? - -

{__("LBRY Early Access")}

- { this.setStage(stage, stageProps) }} /> -
: - { this.setStage(stage, stageProps) }} {...this.state.stageProps} /> - ); - } + return this.state.stage != 'welcome' + ? +

{__('LBRY Early Access')}

+ { + this.setStage(stage, stageProps); + }} + /> +
+ : { + this.setStage(stage, stageProps); + }} + {...this.state.stageProps} + />; + } } diff --git a/ui/js/component/common.js b/ui/js/component/common.js index cc5578f1a..dc9c02816 100644 --- a/ui/js/component/common.js +++ b/ui/js/component/common.js @@ -3,155 +3,202 @@ import lbry from '../lbry.js'; //component/icon.js export class Icon extends React.Component { - static propTypes = { - icon: React.PropTypes.string.isRequired, - className: React.PropTypes.string, - fixed: React.PropTypes.bool, - } + static propTypes = { + icon: React.PropTypes.string.isRequired, + className: React.PropTypes.string, + fixed: React.PropTypes.bool + }; - render() { - const {fixed, className} = this.props; - const spanClassName = ('icon ' + ('fixed' in this.props ? 'icon-fixed-width ' : '') + - this.props.icon + ' ' + (this.props.className || '')); - return - } + render() { + const { fixed, className } = this.props; + const spanClassName = + 'icon ' + + ('fixed' in this.props ? 'icon-fixed-width ' : '') + + this.props.icon + + ' ' + + (this.props.className || ''); + return ; + } } export class TruncatedText extends React.Component { - static propTypes = { - lines: React.PropTypes.number, - } + static propTypes = { + lines: React.PropTypes.number + }; - static defaultProps = { - lines: null - } + static defaultProps = { + lines: null + }; - render() { - return {this.props.children}; - } + render() { + return ( + + {this.props.children} + + ); + } } export class BusyMessage extends React.Component { - static propTypes = { - message: React.PropTypes.string, - } + static propTypes = { + message: React.PropTypes.string + }; - render() { - return {this.props.message} - } + render() { + return ( + {this.props.message} + ); + } } export class CurrencySymbol extends React.Component { - render() { - return LBC; - } + render() { + return LBC; + } } export class CreditAmount extends React.Component { - static propTypes = { - amount: React.PropTypes.number.isRequired, - precision: React.PropTypes.number, - isEstimate: React.PropTypes.bool, - label: React.PropTypes.bool, - showFree: React.PropTypes.bool, - look: React.PropTypes.oneOf(['indicator', 'plain']), - } + static propTypes = { + amount: React.PropTypes.number.isRequired, + precision: React.PropTypes.number, + isEstimate: React.PropTypes.bool, + label: React.PropTypes.bool, + showFree: React.PropTypes.bool, + look: React.PropTypes.oneOf(['indicator', 'plain']) + }; - static defaultProps = { - precision: 1, - label: true, - showFree: false, - look: 'indicator', - } + static defaultProps = { + precision: 1, + label: true, + showFree: false, + look: 'indicator' + }; - render() { - const formattedAmount = lbry.formatCredits(this.props.amount, this.props.precision); - let amountText; - if (this.props.showFree && parseFloat(formattedAmount) == 0) { - amountText = __('free'); - } else if (this.props.label) { - amountText = formattedAmount + ' ' + (parseFloat(formattedAmount) == 1 ? __('credit') : __('credits')); - } else { - amountText = formattedAmount; - } + render() { + const formattedAmount = lbry.formatCredits( + this.props.amount, + this.props.precision + ); + let amountText; + if (this.props.showFree && parseFloat(formattedAmount) == 0) { + amountText = __('free'); + } else if (this.props.label) { + amountText = + formattedAmount + + ' ' + + (parseFloat(formattedAmount) == 1 ? __('credit') : __('credits')); + } else { + amountText = formattedAmount; + } - return ( - - - {amountText} - - { this.props.isEstimate ? * : null } - - ); - } + return ( + + + {amountText} + + {this.props.isEstimate + ? + * + + : null} + + ); + } } let addressStyle = { - fontFamily: '"Consolas", "Lucida Console", "Adobe Source Code Pro", monospace', + fontFamily: '"Consolas", "Lucida Console", "Adobe Source Code Pro", monospace' }; export class Address extends React.Component { - static propTypes = { - address: React.PropTypes.string, - } + static propTypes = { + address: React.PropTypes.string + }; - constructor(props) { - super(props); + constructor(props) { + super(props); - this._inputElem = null; - } + this._inputElem = null; + } - render() { - return ( - { this._inputElem = input; }} - onFocus={() => { this._inputElem.select(); }} style={addressStyle} readOnly="readonly" value={this.props.address}> - ); - } + render() { + return ( + { + this._inputElem = input; + }} + onFocus={() => { + this._inputElem.select(); + }} + style={addressStyle} + readOnly="readonly" + value={this.props.address} + /> + ); + } } export class Thumbnail extends React.Component { - static propTypes = { - src: React.PropTypes.string, - } + static propTypes = { + src: React.PropTypes.string + }; - handleError() { - if (this.state.imageUrl != this._defaultImageUri) { - this.setState({ - imageUri: this._defaultImageUri, - }); - } - } + handleError() { + if (this.state.imageUrl != this._defaultImageUri) { + this.setState({ + imageUri: this._defaultImageUri + }); + } + } - constructor(props) { - super(props); + constructor(props) { + super(props); - this._defaultImageUri = lbry.imagePath('default-thumb.svg') - this._maxLoadTime = 10000 - this._isMounted = false + this._defaultImageUri = lbry.imagePath('default-thumb.svg'); + this._maxLoadTime = 10000; + this._isMounted = false; - this.state = { - imageUri: this.props.src || this._defaultImageUri, - }; - } + this.state = { + imageUri: this.props.src || this._defaultImageUri + }; + } - componentDidMount() { - this._isMounted = true; - setTimeout(() => { - if (this._isMounted && !this.refs.img.complete) { - this.setState({ - imageUri: this._defaultImageUri, - }); - } - }, this._maxLoadTime); - } + componentDidMount() { + this._isMounted = true; + setTimeout(() => { + if (this._isMounted && !this.refs.img.complete) { + this.setState({ + imageUri: this._defaultImageUri + }); + } + }, this._maxLoadTime); + } - componentWillUnmount() { - this._isMounted = false; - } + componentWillUnmount() { + this._isMounted = false; + } - render() { - const className = this.props.className ? this.props.className : '', - otherProps = Object.assign({}, this.props) - delete otherProps.className; - return { this.handleError() }} {...otherProps} className={className} src={this.state.imageUri} /> - } + render() { + const className = this.props.className ? this.props.className : '', + otherProps = Object.assign({}, this.props); + delete otherProps.className; + return ( + { + this.handleError(); + }} + {...otherProps} + className={className} + src={this.state.imageUri} + /> + ); + } } diff --git a/ui/js/component/downloadingModal/index.jsx b/ui/js/component/downloadingModal/index.jsx index 618f335fb..3fcab8b98 100644 --- a/ui/js/component/downloadingModal/index.jsx +++ b/ui/js/component/downloadingModal/index.jsx @@ -1,25 +1,17 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import { - doStartUpgrade, - doCancelUpgrade, -} from 'actions/app' -import { - selectDownloadProgress, - selectDownloadComplete, -} from 'selectors/app' -import DownloadingModal from './view' +import React from 'react'; +import { connect } from 'react-redux'; +import { doStartUpgrade, doCancelUpgrade } from 'actions/app'; +import { selectDownloadProgress, selectDownloadComplete } from 'selectors/app'; +import DownloadingModal from './view'; -const select = (state) => ({ - downloadProgress: selectDownloadProgress(state), - downloadComplete: selectDownloadComplete(state), -}) +const select = state => ({ + downloadProgress: selectDownloadProgress(state), + downloadComplete: selectDownloadComplete(state) +}); -const perform = (dispatch) => ({ - startUpgrade: () => dispatch(doStartUpgrade()), - cancelUpgrade: () => dispatch(doCancelUpgrade()) -}) +const perform = dispatch => ({ + startUpgrade: () => dispatch(doStartUpgrade()), + cancelUpgrade: () => dispatch(doCancelUpgrade()) +}); -export default connect(select, perform)(DownloadingModal) +export default connect(select, perform)(DownloadingModal); diff --git a/ui/js/component/downloadingModal/view.jsx b/ui/js/component/downloadingModal/view.jsx index 053668437..fb29184f9 100644 --- a/ui/js/component/downloadingModal/view.jsx +++ b/ui/js/component/downloadingModal/view.jsx @@ -1,40 +1,62 @@ -import React from 'react' -import { - Modal -} from 'component/modal' -import {Line} from 'rc-progress'; -import Link from 'component/link' +import React from 'react'; +import { Modal } from 'component/modal'; +import { Line } from 'rc-progress'; +import Link from 'component/link'; class DownloadingModal extends React.Component { - render() { - const { - downloadProgress, - downloadComplete, - startUpgrade, - cancelUpgrade, - } = this.props + render() { + const { + downloadProgress, + downloadComplete, + startUpgrade, + cancelUpgrade + } = this.props; - return ( - - {__("Downloading Update")}{downloadProgress ? `: ${downloadProgress}%` : null} - - {downloadComplete ? ( -
-
-

{__("Click \"Begin Upgrade\" to start the upgrade process.")}

-

{__("The app will close, and you will be prompted to install the latest version of LBRY.")}

-

{__("After the install is complete, please reopen the app.")}

-
- ) : null } -
- {downloadComplete - ? - : null} - -
-
- ) - } + return ( + + {__('Downloading Update')} + {downloadProgress ? `: ${downloadProgress}%` : null} + + {downloadComplete + ?
+
+

{__('Click "Begin Upgrade" to start the upgrade process.')}

+

+ {__( + 'The app will close, and you will be prompted to install the latest version of LBRY.' + )} +

+

+ {__('After the install is complete, please reopen the app.')} +

+
+ : null} +
+ {downloadComplete + ? + : null} + +
+
+ ); + } } -export default DownloadingModal +export default DownloadingModal; diff --git a/ui/js/component/errorModal/index.jsx b/ui/js/component/errorModal/index.jsx index e4e4bc24b..3fb546adc 100644 --- a/ui/js/component/errorModal/index.jsx +++ b/ui/js/component/errorModal/index.jsx @@ -1,23 +1,16 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import { - selectCurrentModal, - selectModalExtraContent, -} from 'selectors/app' -import { - doCloseModal, -} from 'actions/app' -import ErrorModal from './view' +import React from 'react'; +import { connect } from 'react-redux'; +import { selectCurrentModal, selectModalExtraContent } from 'selectors/app'; +import { doCloseModal } from 'actions/app'; +import ErrorModal from './view'; -const select = (state) => ({ - modal: selectCurrentModal(state), - error: selectModalExtraContent(state), -}) +const select = state => ({ + modal: selectCurrentModal(state), + error: selectModalExtraContent(state) +}); -const perform = (dispatch) => ({ - closeModal: () => dispatch(doCloseModal()) -}) +const perform = dispatch => ({ + closeModal: () => dispatch(doCloseModal()) +}); -export default connect(select, perform)(ErrorModal) +export default connect(select, perform)(ErrorModal); diff --git a/ui/js/component/errorModal/view.jsx b/ui/js/component/errorModal/view.jsx index a5cbcd8c7..5994e0771 100644 --- a/ui/js/component/errorModal/view.jsx +++ b/ui/js/component/errorModal/view.jsx @@ -1,54 +1,63 @@ -import React from 'react' -import lbry from 'lbry' -import { - ExpandableModal -} from 'component/modal' +import React from 'react'; +import lbry from 'lbry'; +import { ExpandableModal } from 'component/modal'; class ErrorModal extends React.Component { - render() { - const { - modal, - closeModal, - error - } = this.props + render() { + const { modal, closeModal, error } = this.props; - const errorObj = typeof error === "string" ? { error: error } : error + const errorObj = typeof error === 'string' ? { error: error } : error; - const error_key_labels = { - connectionString: __('API connection string'), - method: __('Method'), - params: __('Parameters'), - code: __('Error code'), - message: __('Error message'), - data: __('Error data'), - } + const error_key_labels = { + connectionString: __('API connection string'), + method: __('Method'), + params: __('Parameters'), + code: __('Error code'), + message: __('Error message'), + data: __('Error data') + }; + const errorInfoList = []; + for (let key of Object.keys(error)) { + let val = typeof error[key] == 'string' + ? error[key] + : JSON.stringify(error[key]); + let label = error_key_labels[key]; + errorInfoList.push( +
  • {label}: {val}
  • + ); + } + const errorInfo = ( +
      {errorInfoList}
    + ); - const errorInfoList = [] - for (let key of Object.keys(error)) { - let val = typeof error[key] == 'string' ? error[key] : JSON.stringify(error[key]); - let label = error_key_labels[key]; - errorInfoList.push(
  • {label}: {val}
  • ); - } - const errorInfo =
      {errorInfoList}
    + return ( + +

    {__('Error')}

    - return( - -

    {__("Error")}

    - -
    -
    -

    {__("We're sorry that LBRY has encountered an error. This has been reported and we will investigate the problem.")}

    -
    -
    - ) - } +
    +
    + +
    +

    + {__( + "We're sorry that LBRY has encountered an error. This has been reported and we will investigate the problem." + )} +

    +
    +
    + ); + } } -export default ErrorModal +export default ErrorModal; diff --git a/ui/js/component/file-selector.js b/ui/js/component/file-selector.js index 786d82caf..acac8749f 100644 --- a/ui/js/component/file-selector.js +++ b/ui/js/component/file-selector.js @@ -1,58 +1,64 @@ import React from 'react'; -const {remote} = require('electron'); +const { remote } = require('electron'); class FileSelector extends React.Component { - static propTypes = { - type: React.PropTypes.oneOf(['file', 'directory']), - initPath: React.PropTypes.string, - onFileChosen: React.PropTypes.func, - } + static propTypes = { + type: React.PropTypes.oneOf(['file', 'directory']), + initPath: React.PropTypes.string, + onFileChosen: React.PropTypes.func + }; - static defaultProps = { - type: 'file', - } + static defaultProps = { + type: 'file' + }; - componentWillMount() { - this.setState({ - path: this.props.initPath || null, - }); - } + componentWillMount() { + this.setState({ + path: this.props.initPath || null + }); + } - handleButtonClick() { - remote.dialog.showOpenDialog({ - properties: [this.props.type == 'file' ? 'openFile' : 'openDirectory'], - }, (paths) => { - if (!paths) { // User hit cancel, so do nothing - return; - } + handleButtonClick() { + remote.dialog.showOpenDialog( + { + properties: [this.props.type == 'file' ? 'openFile' : 'openDirectory'] + }, + paths => { + if (!paths) { + // User hit cancel, so do nothing + return; + } - const path = paths[0]; - this.setState({ - path: path, - }); - if (this.props.onFileChosen) { - this.props.onFileChosen(path); - } - }); - } + const path = paths[0]; + this.setState({ + path: path + }); + if (this.props.onFileChosen) { + this.props.onFileChosen(path); + } + } + ); + } - render() { - return ( -
    - - {' '} - - {this.state.path ? - this.state.path : - __('No File Chosen')} - -
    - ); - } -}; + render() { + return ( +
    + + {' '} + + {this.state.path ? this.state.path : __('No File Chosen')} + +
    + ); + } +} export default FileSelector; diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 1d8ba6088..6efc48287 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -1,75 +1,56 @@ -import React from 'react' +import React from 'react'; +import { connect } from 'react-redux'; +import { selectPlatform } from 'selectors/app'; import { - connect, -} from 'react-redux' + makeSelectFileInfoForUri, + makeSelectDownloadingForUri, + makeSelectLoadingForUri +} from 'selectors/file_info'; +import { makeSelectIsAvailableForUri } from 'selectors/availability'; +import { selectCurrentModal } from 'selectors/app'; +import { makeSelectCostInfoForUri } from 'selectors/cost_info'; +import { doCloseModal, doOpenModal, doHistoryBack } from 'actions/app'; +import { doFetchAvailability } from 'actions/availability'; import { - selectPlatform, -} from 'selectors/app' -import { - makeSelectFileInfoForUri, - makeSelectDownloadingForUri, - makeSelectLoadingForUri, -} from 'selectors/file_info' -import { - makeSelectIsAvailableForUri, -} from 'selectors/availability' -import { - selectCurrentModal, -} from 'selectors/app' -import { - makeSelectCostInfoForUri, -} from 'selectors/cost_info' -import { - doCloseModal, - doOpenModal, - doHistoryBack, -} from 'actions/app' -import { - doFetchAvailability -} from 'actions/availability' -import { - doOpenFileInShell, - doOpenFileInFolder, - doDeleteFile, -} from 'actions/file_info' -import { - doPurchaseUri, - doLoadVideo, -} from 'actions/content' -import FileActions from './view' + doOpenFileInShell, + doOpenFileInFolder, + doDeleteFile +} from 'actions/file_info'; +import { doPurchaseUri, doLoadVideo } from 'actions/content'; +import FileActions from './view'; const makeSelect = () => { - const selectFileInfoForUri = makeSelectFileInfoForUri() - const selectIsAvailableForUri = makeSelectIsAvailableForUri() - const selectDownloadingForUri = makeSelectDownloadingForUri() - const selectCostInfoForUri = makeSelectCostInfoForUri() - const selectLoadingForUri = makeSelectLoadingForUri() + const selectFileInfoForUri = makeSelectFileInfoForUri(); + const selectIsAvailableForUri = makeSelectIsAvailableForUri(); + const selectDownloadingForUri = makeSelectDownloadingForUri(); + const selectCostInfoForUri = makeSelectCostInfoForUri(); + const selectLoadingForUri = makeSelectLoadingForUri(); - const select = (state, props) => ({ - fileInfo: selectFileInfoForUri(state, props), - isAvailable: selectIsAvailableForUri(state, props), - platform: selectPlatform(state), - modal: selectCurrentModal(state), - downloading: selectDownloadingForUri(state, props), - costInfo: selectCostInfoForUri(state, props), - loading: selectLoadingForUri(state, props), - }) + const select = (state, props) => ({ + fileInfo: selectFileInfoForUri(state, props), + isAvailable: selectIsAvailableForUri(state, props), + platform: selectPlatform(state), + modal: selectCurrentModal(state), + downloading: selectDownloadingForUri(state, props), + costInfo: selectCostInfoForUri(state, props), + loading: selectLoadingForUri(state, props) + }); - return select -} + return select; +}; -const perform = (dispatch) => ({ - checkAvailability: (uri) => dispatch(doFetchAvailability(uri)), - closeModal: () => dispatch(doCloseModal()), - openInFolder: (fileInfo) => dispatch(doOpenFileInFolder(fileInfo)), - openInShell: (fileInfo) => dispatch(doOpenFileInShell(fileInfo)), - deleteFile: (fileInfo, deleteFromComputer) => { - dispatch(doHistoryBack()) - dispatch(doDeleteFile(fileInfo, deleteFromComputer)) - }, - openModal: (modal) => dispatch(doOpenModal(modal)), - startDownload: (uri) => dispatch(doPurchaseUri(uri, 'affirmPurchase')), - loadVideo: (uri) => dispatch(doLoadVideo(uri)), -}) +const perform = dispatch => ({ + checkAvailability: uri => dispatch(doFetchAvailability(uri)), + closeModal: () => dispatch(doCloseModal()), + openInFolder: fileInfo => dispatch(doOpenFileInFolder(fileInfo)), + openInShell: fileInfo => dispatch(doOpenFileInShell(fileInfo)), + deleteFile: (fileInfo, deleteFromComputer) => { + dispatch(doHistoryBack()); + dispatch(doDeleteFile(fileInfo, deleteFromComputer)); + }, + openModal: modal => dispatch(doOpenModal(modal)), + startDownload: uri => dispatch(doPurchaseUri(uri, 'affirmPurchase')), + loadVideo: uri => dispatch(doLoadVideo(uri)) +}); -export default connect(makeSelect, perform)(FileActions) \ No newline at end of file +export default connect(makeSelect, perform)(FileActions); diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 0d45514f7..4d83f30a9 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -1,151 +1,222 @@ import React from 'react'; -import {Icon,BusyMessage} from 'component/common'; -import FilePrice from 'component/filePrice' -import {Modal} from 'component/modal'; -import {FormField} from 'component/form'; +import { Icon, BusyMessage } from 'component/common'; +import FilePrice from 'component/filePrice'; +import { Modal } from 'component/modal'; +import { FormField } from 'component/form'; import Link from 'component/link'; -import {ToolTip} from 'component/tooltip'; -import {DropDownMenu, DropDownMenuItem} from 'component/menu'; +import { ToolTip } from 'component/tooltip'; +import { DropDownMenu, DropDownMenuItem } from 'component/menu'; class FileActions extends React.Component { - constructor(props) { - super(props) - this.state = { - forceShowActions: false, - deleteChecked: false, - } - } + constructor(props) { + super(props); + this.state = { + forceShowActions: false, + deleteChecked: false + }; + } - componentWillMount() { - this.checkAvailability(this.props.uri) - } + componentWillMount() { + this.checkAvailability(this.props.uri); + } - componentWillReceiveProps(nextProps) { - this.checkAvailability(nextProps.uri) - } + componentWillReceiveProps(nextProps) { + this.checkAvailability(nextProps.uri); + } - checkAvailability(uri) { - if (!this._uri || uri !== this._uri) { - this._uri = uri; - this.props.checkAvailability(uri) - } - } + checkAvailability(uri) { + if (!this._uri || uri !== this._uri) { + this._uri = uri; + this.props.checkAvailability(uri); + } + } - onShowFileActionsRowClicked() { - this.setState({ - forceShowActions: true, - }); - } + onShowFileActionsRowClicked() { + this.setState({ + forceShowActions: true + }); + } - handleDeleteCheckboxClicked(event) { - this.setState({ - deleteChecked: event.target.checked, - }) - } + handleDeleteCheckboxClicked(event) { + this.setState({ + deleteChecked: event.target.checked + }); + } - onAffirmPurchase() { - this.props.closeModal() - this.props.loadVideo(this.props.uri) - } + onAffirmPurchase() { + this.props.closeModal(); + this.props.loadVideo(this.props.uri); + } - render() { - const { - fileInfo, - isAvailable, - platform, - downloading, - uri, - deleteFile, - openInFolder, - openInShell, - modal, - openModal, - closeModal, - startDownload, - costInfo, - loading, - } = this.props + render() { + const { + fileInfo, + isAvailable, + platform, + downloading, + uri, + deleteFile, + openInFolder, + openInShell, + modal, + openModal, + closeModal, + startDownload, + costInfo, + loading + } = this.props; - const deleteChecked = this.state.deleteChecked, - metadata = fileInfo ? fileInfo.metadata : null, - openInFolderMessage = platform.startsWith('Mac') ? __('Open in Finder') : __('Open in Folder'), - showMenu = fileInfo && Object.keys(fileInfo).length > 0, - title = metadata ? metadata.title : uri; + const deleteChecked = this.state.deleteChecked, + metadata = fileInfo ? fileInfo.metadata : null, + openInFolderMessage = platform.startsWith('Mac') + ? __('Open in Finder') + : __('Open in Folder'), + showMenu = fileInfo && Object.keys(fileInfo).length > 0, + title = metadata ? metadata.title : uri; - let content + let content; - if (loading || downloading) { + if (loading || downloading) { + const progress = fileInfo && fileInfo.written_bytes + ? fileInfo.written_bytes / fileInfo.total_bytes * 100 + : 0, + label = fileInfo + ? progress.toFixed(0) + __('% complete') + : __('Connecting...'), + labelWithIcon = ( + + {label} + + ); - const - progress = (fileInfo && fileInfo.written_bytes) ? fileInfo.written_bytes / fileInfo.total_bytes * 100 : 0, - label = fileInfo ? progress.toFixed(0) + __('% complete') : __('Connecting...'), - labelWithIcon = {label}; + content = ( +
    +
    + {labelWithIcon} +
    + {labelWithIcon} +
    + ); + } else if (!fileInfo && isAvailable === undefined) { + content = ; + } else if (!fileInfo && !isAvailable && !this.state.forceShowActions) { + content = ( +
    +
    + {__('Content unavailable.')} +
    + + +
    + ); + } else if (fileInfo === null && !downloading) { + if (!costInfo) { + content = ; + } else { + content = ( + { + startDownload(uri); + }} + /> + ); + } + } else if (fileInfo && fileInfo.download_path) { + content = ( + openInShell(fileInfo)} + /> + ); + } else { + console.log('handle this case of file action props?'); + } - content =
    -
    {labelWithIcon}
    - {labelWithIcon} -
    + return ( +
    + {content} + {showMenu + ? + openInFolder(fileInfo)} + label={openInFolderMessage} + /> + openModal('confirmRemove')} + label={__('Remove...')} + /> + + : ''} + + {__('This will purchase')} {title} {__('for')} + {' '} + {' '}{__('credits')}. + + + {__("You don't have enough LBRY credits to pay for this stream.")} + + + {__('LBRY was unable to download the stream')} {uri}. + + deleteFile(fileInfo.outpoint, deleteChecked)} + onAborted={closeModal} + > +

    + {__("Are you sure you'd like to remove")} {title} + {' '}{__('from LBRY?')} +

    - } else if (!fileInfo && isAvailable === undefined) { - - content = - - } else if (!fileInfo && !isAvailable && !this.state.forceShowActions) { - - content =
    -
    {__("Content unavailable.")}
    - - -
    - - } else if (fileInfo === null && !downloading) { - if (!costInfo) { - content = - } else { - content = { startDownload(uri) } } />; - } - - } else if (fileInfo && fileInfo.download_path) { - content = openInShell(fileInfo)} />; - } else { - console.log('handle this case of file action props?'); - } - - return ( -
    - { content } - { showMenu ? - - openInFolder(fileInfo)} label={openInFolderMessage} /> - openModal('confirmRemove')} label={__("Remove...")} /> - : '' } - - {__("This will purchase")} {title} {__("for")} {__("credits")}. - - - {__("You don't have enough LBRY credits to pay for this stream.")} - - - {__("LBRY was unable to download the stream")} {uri}. - - deleteFile(fileInfo.outpoint, deleteChecked)} - onAborted={closeModal}> -

    {__("Are you sure you'd like to remove")} {title} {__("from LBRY?")}

    - - -
    -
    - ); - } + +
    +
    + ); + } } -export default FileActions +export default FileActions; diff --git a/ui/js/component/fileCard/index.js b/ui/js/component/fileCard/index.js index 89ebc5040..2d17912b9 100644 --- a/ui/js/component/fileCard/index.js +++ b/ui/js/component/fileCard/index.js @@ -1,50 +1,37 @@ -import React from 'react' +import React from 'react'; +import { connect } from 'react-redux'; +import { doNavigate } from 'actions/app'; +import { doResolveUri, doCancelResolveUri } from 'actions/content'; +import { selectObscureNsfw } from 'selectors/app'; import { - connect -} from 'react-redux' -import { - doNavigate, -} from 'actions/app' -import { - doResolveUri, - doCancelResolveUri, -} from 'actions/content' -import { - selectObscureNsfw, -} from 'selectors/app' -import { - makeSelectClaimForUri, - makeSelectMetadataForUri, -} from 'selectors/claims' -import { - makeSelectFileInfoForUri, -} from 'selectors/file_info' -import { - makeSelectIsResolvingForUri, -} from 'selectors/content' -import FileCard from './view' + makeSelectClaimForUri, + makeSelectMetadataForUri +} from 'selectors/claims'; +import { makeSelectFileInfoForUri } from 'selectors/file_info'; +import { makeSelectIsResolvingForUri } from 'selectors/content'; +import FileCard from './view'; const makeSelect = () => { - const selectClaimForUri = makeSelectClaimForUri() - const selectFileInfoForUri = makeSelectFileInfoForUri() - const selectMetadataForUri = makeSelectMetadataForUri() - const selectResolvingUri = makeSelectIsResolvingForUri() + const selectClaimForUri = makeSelectClaimForUri(); + const selectFileInfoForUri = makeSelectFileInfoForUri(); + const selectMetadataForUri = makeSelectMetadataForUri(); + const selectResolvingUri = makeSelectIsResolvingForUri(); - const select = (state, props) => ({ - claim: selectClaimForUri(state, props), - fileInfo: selectFileInfoForUri(state, props), - obscureNsfw: selectObscureNsfw(state), - metadata: selectMetadataForUri(state, props), - isResolvingUri: selectResolvingUri(state, props), - }) + const select = (state, props) => ({ + claim: selectClaimForUri(state, props), + fileInfo: selectFileInfoForUri(state, props), + obscureNsfw: selectObscureNsfw(state), + metadata: selectMetadataForUri(state, props), + isResolvingUri: selectResolvingUri(state, props) + }); - return select -} + return select; +}; -const perform = (dispatch) => ({ - navigate: (path, params) => dispatch(doNavigate(path, params)), - resolveUri: (uri) => dispatch(doResolveUri(uri)), - cancelResolveUri: (uri) => dispatch(doCancelResolveUri(uri)) -}) +const perform = dispatch => ({ + navigate: (path, params) => dispatch(doNavigate(path, params)), + resolveUri: uri => dispatch(doResolveUri(uri)), + cancelResolveUri: uri => dispatch(doCancelResolveUri(uri)) +}); -export default connect(makeSelect, perform)(FileCard) +export default connect(makeSelect, perform)(FileCard); diff --git a/ui/js/component/fileCard/view.jsx b/ui/js/component/fileCard/view.jsx index d333c03c9..36cc68e69 100644 --- a/ui/js/component/fileCard/view.jsx +++ b/ui/js/component/fileCard/view.jsx @@ -2,111 +2,121 @@ import React from 'react'; import lbry from 'lbry.js'; import lbryuri from 'lbryuri.js'; import Link from 'component/link'; -import {Thumbnail, TruncatedText, Icon} from 'component/common'; -import FilePrice from 'component/filePrice' +import { Thumbnail, TruncatedText, Icon } from 'component/common'; +import FilePrice from 'component/filePrice'; import UriIndicator from 'component/uriIndicator'; class FileCard extends React.Component { - componentWillMount() { - this.resolve(this.props) - } + componentWillMount() { + this.resolve(this.props); + } - componentWillReceiveProps(nextProps) { - this.resolve(nextProps) - } + componentWillReceiveProps(nextProps) { + this.resolve(nextProps); + } - resolve(props) { - const { - isResolvingUri, - resolveUri, - claim, - uri, - } = props + resolve(props) { + const { isResolvingUri, resolveUri, claim, uri } = props; - if(!isResolvingUri && claim === undefined && uri) { - resolveUri(uri) - } - } + if (!isResolvingUri && claim === undefined && uri) { + resolveUri(uri); + } + } - componentWillUnmount() { - const { - isResolvingUri, - cancelResolveUri, - uri - } = this.props + componentWillUnmount() { + const { isResolvingUri, cancelResolveUri, uri } = this.props; - if (isResolvingUri) { - cancelResolveUri(uri) - } - } + if (isResolvingUri) { + cancelResolveUri(uri); + } + } - handleMouseOver() { - this.setState({ - hovered: true, - }); - } + handleMouseOver() { + this.setState({ + hovered: true + }); + } - handleMouseOut() { - this.setState({ - hovered: false, - }); - } + handleMouseOut() { + this.setState({ + hovered: false + }); + } - render() { + render() { + const { claim, fileInfo, metadata, isResolvingUri, navigate } = this.props; - const { - claim, - fileInfo, - metadata, - isResolvingUri, - navigate, - } = this.props + const uri = lbryuri.normalize(this.props.uri); + const title = !isResolvingUri && metadata && metadata.title + ? metadata.title + : uri; + const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw; - const uri = lbryuri.normalize(this.props.uri); - const title = !isResolvingUri && metadata && metadata.title ? metadata.title : uri; - const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw; + let description = ''; + if (isResolvingUri) { + description = __('Loading...'); + } else if (metadata && metadata.description) { + description = metadata.description; + } else if (claim === null) { + description = __('This address contains no content.'); + } - let description = "" - if (isResolvingUri) { - description = __("Loading...") - } else if (metadata && metadata.description) { - description = metadata.description - } else if (claim === null) { - description = __("This address contains no content.") - } - - return ( -
    -
    - navigate('/show', { uri })} className="card__link"> -
    -
    {title}
    -
    - - - { fileInfo ? {' '} : '' } - - -
    -
    - {metadata && metadata.thumbnail && -
    - } -
    - {description} -
    - - {obscureNsfw && this.state.hovered - ?
    -

    - {__("This content is Not Safe For Work. To view adult content, please change your")} navigate('settings')} label={__("Settings")} />. -

    -
    - : null} -
    -
    - ); - } + return ( +
    +
    + navigate('/show', { uri })} + className="card__link" + > +
    +
    + {title} +
    +
    + + + {fileInfo + ? {' '} + : ''} + + +
    +
    + {metadata && + metadata.thumbnail && +
    } +
    + {description} +
    + + {obscureNsfw && this.state.hovered + ?
    +

    + {__( + 'This content is Not Safe For Work. To view adult content, please change your' + )} + {' '} navigate('settings')} + label={__('Settings')} + />. +

    +
    + : null} +
    +
    + ); + } } -export default FileCard +export default FileCard; diff --git a/ui/js/component/fileList/index.js b/ui/js/component/fileList/index.js index dd0209b40..3b6ced934 100644 --- a/ui/js/component/fileList/index.js +++ b/ui/js/component/fileList/index.js @@ -1,13 +1,9 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import FileList from './view' +import React from 'react'; +import { connect } from 'react-redux'; +import FileList from './view'; -const select = (state) => ({ -}) +const select = state => ({}); -const perform = (dispatch) => ({ -}) +const perform = dispatch => ({}); -export default connect(select, perform)(FileList) +export default connect(select, perform)(FileList); diff --git a/ui/js/component/fileList/view.jsx b/ui/js/component/fileList/view.jsx index cd85a7b84..8c62944b3 100644 --- a/ui/js/component/fileList/view.jsx +++ b/ui/js/component/fileList/view.jsx @@ -2,92 +2,99 @@ import React from 'react'; import lbry from 'lbry.js'; import lbryuri from 'lbryuri.js'; import Link from 'component/link'; -import {FormField} from 'component/form.js'; +import { FormField } from 'component/form.js'; import FileTile from 'component/fileTile'; import rewards from 'rewards.js'; import lbryio from 'lbryio.js'; -import {BusyMessage, Thumbnail} from 'component/common.js'; +import { BusyMessage, Thumbnail } from 'component/common.js'; class FileList extends React.Component { - constructor(props) { - super(props) + constructor(props) { + super(props); - this.state = { - sortBy: 'date', - } + this.state = { + sortBy: 'date' + }; - this._sortFunctions = { - date: function(fileInfos) { - return fileInfos.slice().reverse(); - }, - title: function(fileInfos) { - return fileInfos.slice().sort(function(fileInfo1, fileInfo2) { - const title1 = fileInfo1.metadata ? fileInfo1.metadata.stream.metadata.title.toLowerCase() : fileInfo1.name; - const title2 = fileInfo2.metadata ? fileInfo2.metadata.stream.metadata.title.toLowerCase() : fileInfo2.name; - if (title1 < title2) { - return -1; - } else if (title1 > title2) { - return 1; - } else { - return 0; - } - }) - }, - filename: function(fileInfos) { - return fileInfos.slice().sort(function({file_name: fileName1}, {file_name: fileName2}) { - const fileName1Lower = fileName1.toLowerCase(); - const fileName2Lower = fileName2.toLowerCase(); - if (fileName1Lower < fileName2Lower) { - return -1; - } else if (fileName2Lower > fileName1Lower) { - return 1; - } else { - return 0; - } - }) - }, - } - } + this._sortFunctions = { + date: function(fileInfos) { + return fileInfos.slice().reverse(); + }, + title: function(fileInfos) { + return fileInfos.slice().sort(function(fileInfo1, fileInfo2) { + const title1 = fileInfo1.metadata + ? fileInfo1.metadata.stream.metadata.title.toLowerCase() + : fileInfo1.name; + const title2 = fileInfo2.metadata + ? fileInfo2.metadata.stream.metadata.title.toLowerCase() + : fileInfo2.name; + if (title1 < title2) { + return -1; + } else if (title1 > title2) { + return 1; + } else { + return 0; + } + }); + }, + filename: function(fileInfos) { + return fileInfos + .slice() + .sort(function({ file_name: fileName1 }, { file_name: fileName2 }) { + const fileName1Lower = fileName1.toLowerCase(); + const fileName2Lower = fileName2.toLowerCase(); + if (fileName1Lower < fileName2Lower) { + return -1; + } else if (fileName2Lower > fileName1Lower) { + return 1; + } else { + return 0; + } + }); + } + }; + } - handleSortChanged(event) { - this.setState({ - sortBy: event.target.value, - }) - } + handleSortChanged(event) { + this.setState({ + sortBy: event.target.value + }); + } - render() { - const { - handleSortChanged, - fetching, - fileInfos, - } = this.props - const { - sortBy, - } = this.state - const content = [] + render() { + const { handleSortChanged, fetching, fileInfos } = this.props; + const { sortBy } = this.state; + const content = []; - this._sortFunctions[sortBy](fileInfos).forEach(fileInfo => { - const uri = lbryuri.build({ - contentName: fileInfo.name, - channelName: fileInfo.channel_name, - }) - content.push() - }) - return ( -
    - { fetching && } - - {__("Sort by")} { ' ' } - - - - - - - {content} -
    - ) - } + this._sortFunctions[sortBy](fileInfos).forEach(fileInfo => { + const uri = lbryuri.build({ + contentName: fileInfo.name, + channelName: fileInfo.channel_name + }); + content.push( + + ); + }); + return ( +
    + {fetching && } + + {__('Sort by')} {' '} + + + + + + + {content} +
    + ); + } } -export default FileList +export default FileList; diff --git a/ui/js/component/fileListSearch/index.js b/ui/js/component/fileListSearch/index.js index ed452052b..c8169c607 100644 --- a/ui/js/component/fileListSearch/index.js +++ b/ui/js/component/fileListSearch/index.js @@ -1,29 +1,23 @@ -import React from 'react' +import React from 'react'; +import { connect } from 'react-redux'; +import { doSearch } from 'actions/search'; 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' + 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 select = state => ({ + isSearching: selectIsSearching(state), + query: selectSearchQuery(state), + results: selectCurrentSearchResults(state) +}); -const perform = (dispatch) => ({ - navigate: (path) => dispatch(doNavigate(path)), - search: (search) => dispatch(doSearch(search)) -}) +const perform = dispatch => ({ + navigate: path => dispatch(doNavigate(path)), + search: search => dispatch(doSearch(search)) +}); -export default connect(select, perform)(FileListSearch) +export default connect(select, perform)(FileListSearch); diff --git a/ui/js/component/fileListSearch/view.jsx b/ui/js/component/fileListSearch/view.jsx index 7666c54fc..0e4d4ef98 100644 --- a/ui/js/component/fileListSearch/view.jsx +++ b/ui/js/component/fileListSearch/view.jsx @@ -3,74 +3,74 @@ 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'; +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 +const SearchNoResults = props => { + const { navigate, query } = props; - return
    - - {__("No one has checked anything in for %s yet."), query} { ' ' } - navigate('/publish')} /> - -
    ; + return ( +
    + + {(__('No one has checked anything in for %s yet.'), query)} {' '} + navigate('/publish')} /> + +
    + ); +}; + +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(); + } + return
    {rows}
    ; +}; + +class FileListSearch extends React.Component { + componentWillMount() { + this.props.search(this.props.query); + } + + render() { + const { isSearching, results } = this.props; + + return ( +
    + {isSearching && + !results && + } + + {isSearching && + results && + } + + {results && !!results.length + ? + : } +
    + ); + } } -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( - - ); - } - return ( -
    {rows}
    - ); -} - -class FileListSearch extends React.Component{ - componentWillMount() { - this.props.search(this.props.query) - } - - render() { - const { - isSearching, - results - } = this.props - - return ( -
    - {isSearching && !results && - } - - {isSearching && results && - } - - {(results && !!results.length) ? - : - } -
    - ) - } -} - -export default FileListSearch +export default FileListSearch; diff --git a/ui/js/component/filePrice/index.js b/ui/js/component/filePrice/index.js index 65e870a58..0e8572783 100644 --- a/ui/js/component/filePrice/index.js +++ b/ui/js/component/filePrice/index.js @@ -1,31 +1,27 @@ -import React from 'react' +import React from 'react'; +import { connect } from 'react-redux'; +import { doFetchCostInfoForUri } from 'actions/cost_info'; import { - connect, -} from 'react-redux' -import { - doFetchCostInfoForUri, -} from 'actions/cost_info' -import { - makeSelectCostInfoForUri, - makeSelectFetchingCostInfoForUri, -} from 'selectors/cost_info' -import FilePrice from './view' + makeSelectCostInfoForUri, + makeSelectFetchingCostInfoForUri +} from 'selectors/cost_info'; +import FilePrice from './view'; const makeSelect = () => { - const selectCostInfoForUri = makeSelectCostInfoForUri() - const selectFetchingCostInfoForUri = makeSelectFetchingCostInfoForUri() + const selectCostInfoForUri = makeSelectCostInfoForUri(); + const selectFetchingCostInfoForUri = makeSelectFetchingCostInfoForUri(); - const select = (state, props) => ({ - costInfo: selectCostInfoForUri(state, props), - fetching: selectFetchingCostInfoForUri(state, props), - }) + const select = (state, props) => ({ + costInfo: selectCostInfoForUri(state, props), + fetching: selectFetchingCostInfoForUri(state, props) + }); - return select -} + return select; +}; -const perform = (dispatch) => ({ - fetchCostInfo: (uri) => dispatch(doFetchCostInfoForUri(uri)), - // cancelFetchCostInfo: (uri) => dispatch(doCancelFetchCostInfoForUri(uri)) -}) +const perform = dispatch => ({ + fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)) + // cancelFetchCostInfo: (uri) => dispatch(doCancelFetchCostInfoForUri(uri)) +}); -export default connect(makeSelect, perform)(FilePrice) +export default connect(makeSelect, perform)(FilePrice); diff --git a/ui/js/component/filePrice/view.jsx b/ui/js/component/filePrice/view.jsx index 2a0872492..67b21c545 100644 --- a/ui/js/component/filePrice/view.jsx +++ b/ui/js/component/filePrice/view.jsx @@ -1,44 +1,43 @@ -import React from 'react' -import { - CreditAmount, -} from 'component/common' +import React from 'react'; +import { CreditAmount } from 'component/common'; -class FilePrice extends React.Component{ - componentWillMount() { - this.fetchCost(this.props) - } +class FilePrice extends React.Component { + componentWillMount() { + this.fetchCost(this.props); + } - componentWillReceiveProps(nextProps) { - this.fetchCost(nextProps) - } + componentWillReceiveProps(nextProps) { + this.fetchCost(nextProps); + } - fetchCost(props) { - const { - costInfo, - fetchCostInfo, - uri, - fetching, - } = props + fetchCost(props) { + const { costInfo, fetchCostInfo, uri, fetching } = props; - if (costInfo === undefined && !fetching) { - fetchCostInfo(uri) - } - } + if (costInfo === undefined && !fetching) { + fetchCostInfo(uri); + } + } - render() { - const { - costInfo, - look = 'indicator', - } = this.props + render() { + const { costInfo, look = 'indicator' } = this.props; - const isEstimate = costInfo ? !costInfo.includesData : null + const isEstimate = costInfo ? !costInfo.includesData : null; - if (!costInfo) { - return ???; - } + if (!costInfo) { + return ( + ??? + ); + } - return - } + return ( + + ); + } } -export default FilePrice +export default FilePrice; diff --git a/ui/js/component/fileTile/index.js b/ui/js/component/fileTile/index.js index d61e58b64..2008df1ad 100644 --- a/ui/js/component/fileTile/index.js +++ b/ui/js/component/fileTile/index.js @@ -1,48 +1,36 @@ -import React from 'react' +import React from 'react'; +import { connect } from 'react-redux'; +import { doNavigate } from 'actions/app'; +import { doResolveUri } from 'actions/content'; import { - connect -} from 'react-redux' -import { - doNavigate, -} from 'actions/app' -import { - doResolveUri, -} from 'actions/content' -import { - makeSelectClaimForUri, - makeSelectMetadataForUri, -} from 'selectors/claims' -import { - makeSelectFileInfoForUri, -} from 'selectors/file_info' -import { - selectObscureNsfw, -} from 'selectors/app' -import { - makeSelectIsResolvingForUri, -} from 'selectors/content' -import FileTile from './view' + makeSelectClaimForUri, + makeSelectMetadataForUri +} from 'selectors/claims'; +import { makeSelectFileInfoForUri } from 'selectors/file_info'; +import { selectObscureNsfw } from 'selectors/app'; +import { makeSelectIsResolvingForUri } from 'selectors/content'; +import FileTile from './view'; const makeSelect = () => { - const selectClaimForUri = makeSelectClaimForUri() - const selectFileInfoForUri = makeSelectFileInfoForUri() - const selectMetadataForUri = makeSelectMetadataForUri() - const selectResolvingUri = makeSelectIsResolvingForUri() + const selectClaimForUri = makeSelectClaimForUri(); + const selectFileInfoForUri = makeSelectFileInfoForUri(); + const selectMetadataForUri = makeSelectMetadataForUri(); + const selectResolvingUri = makeSelectIsResolvingForUri(); - const select = (state, props) => ({ - claim: selectClaimForUri(state, props), - fileInfo: selectFileInfoForUri(state, props), - obscureNsfw: selectObscureNsfw(state), - metadata: selectMetadataForUri(state, props), - isResolvingUri: selectResolvingUri(state, props), - }) + const select = (state, props) => ({ + claim: selectClaimForUri(state, props), + fileInfo: selectFileInfoForUri(state, props), + obscureNsfw: selectObscureNsfw(state), + metadata: selectMetadataForUri(state, props), + isResolvingUri: selectResolvingUri(state, props) + }); - return select -} + return select; +}; -const perform = (dispatch) => ({ - navigate: (path, params) => dispatch(doNavigate(path, params)), - resolveUri: (uri) => dispatch(doResolveUri(uri)), -}) +const perform = dispatch => ({ + navigate: (path, params) => dispatch(doNavigate(path, params)), + resolveUri: uri => dispatch(doResolveUri(uri)) +}); -export default connect(makeSelect, perform)(FileTile) \ No newline at end of file +export default connect(makeSelect, perform)(FileTile); diff --git a/ui/js/component/fileTile/view.jsx b/ui/js/component/fileTile/view.jsx index 610ad2d28..1d26f1e17 100644 --- a/ui/js/component/fileTile/view.jsx +++ b/ui/js/component/fileTile/view.jsx @@ -3,113 +3,140 @@ import lbry from 'lbry.js'; import lbryuri from 'lbryuri.js'; import Link from 'component/link'; import FileActions from 'component/fileActions'; -import {Thumbnail, TruncatedText,} from 'component/common.js'; -import FilePrice from 'component/filePrice' +import { Thumbnail, TruncatedText } from 'component/common.js'; +import FilePrice from 'component/filePrice'; import UriIndicator from 'component/uriIndicator'; class FileTile extends React.Component { - static SHOW_EMPTY_PUBLISH = "publish" - static SHOW_EMPTY_PENDING = "pending" + static SHOW_EMPTY_PUBLISH = 'publish'; + static SHOW_EMPTY_PENDING = 'pending'; - constructor(props) { - super(props) - this.state = { - showNsfwHelp: false, - } - } + constructor(props) { + super(props); + this.state = { + showNsfwHelp: false + }; + } - componentDidMount() { - const { - isResolvingUri, - resolveUri, - claim, - uri, - } = this.props + componentDidMount() { + const { isResolvingUri, resolveUri, claim, uri } = this.props; - if(!isResolvingUri && !claim && uri) { - resolveUri(uri) - } - } + if (!isResolvingUri && !claim && uri) { + resolveUri(uri); + } + } - handleMouseOver() { - if (this.props.obscureNsfw && this.props.metadata && this.props.metadata.nsfw) { - this.setState({ - showNsfwHelp: true, - }); - } - } + handleMouseOver() { + if ( + this.props.obscureNsfw && + this.props.metadata && + this.props.metadata.nsfw + ) { + this.setState({ + showNsfwHelp: true + }); + } + } - handleMouseOut() { - if (this.state.showNsfwHelp) { - this.setState({ - showNsfwHelp: false, - }); - } - } + handleMouseOut() { + if (this.state.showNsfwHelp) { + this.setState({ + showNsfwHelp: false + }); + } + } - render() { - const { - claim, - metadata, - isResolvingUri, - showEmpty, - navigate, - hidePrice, - } = this.props + render() { + const { + claim, + metadata, + isResolvingUri, + showEmpty, + navigate, + hidePrice + } = this.props; - const uri = lbryuri.normalize(this.props.uri); - const isClaimed = !!claim; - const isClaimable = lbryuri.isClaimable(uri) - const title = isClaimed && metadata && metadata.title ? metadata.title : uri; - const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw; - let onClick = () => navigate('/show', { uri }) + const uri = lbryuri.normalize(this.props.uri); + const isClaimed = !!claim; + const isClaimable = lbryuri.isClaimable(uri); + const title = isClaimed && metadata && metadata.title + ? metadata.title + : uri; + const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw; + let onClick = () => navigate('/show', { uri }); - let description = "" - if (isClaimed) { - description = metadata && metadata.description - } else if (isResolvingUri) { - description = __("Loading...") - } else if (showEmpty === FileTile.SHOW_EMPTY_PUBLISH) { - onClick = () => navigate('/publish', { }) - description = - {__("This location is unused.")} { ' ' } - { isClaimable && {__("Put something here!")} } - - } else if (showEmpty === FileTile.SHOW_EMPTY_PENDING) { - description = {__("This file is pending confirmation.")} - } + let description = ''; + if (isClaimed) { + description = metadata && metadata.description; + } else if (isResolvingUri) { + description = __('Loading...'); + } else if (showEmpty === FileTile.SHOW_EMPTY_PUBLISH) { + onClick = () => navigate('/publish', {}); + description = ( + + {__('This location is unused.')} {' '} + {isClaimable && + {__('Put something here!')}} + + ); + } else if (showEmpty === FileTile.SHOW_EMPTY_PENDING) { + description = ( + + {__('This file is pending confirmation.')} + + ); + } - return ( -
    - -
    -
    -
    -
    -
    - { !hidePrice ? : null} -
    {uri}
    -

    {title}

    -
    -
    - - {description} - -
    -
    -
    - - {this.state.showNsfwHelp - ?
    -

    - {__("This content is Not Safe For Work. To view adult content, please change your")} navigate('/settings')} label={__("Settings")} />. -

    -
    - : null} -
    - ); - } + return ( +
    + +
    +
    +
    +
    + {!hidePrice ? : null} +
    {uri}
    +

    {title}

    +
    +
    + + {description} + +
    +
    +
    + + {this.state.showNsfwHelp + ?
    +

    + {__( + 'This content is Not Safe For Work. To view adult content, please change your' + )} + {' '} navigate('/settings')} + label={__('Settings')} + />. +

    +
    + : null} +
    + ); + } } -export default FileTile +export default FileTile; diff --git a/ui/js/component/form.js b/ui/js/component/form.js index 809ebe534..299961a44 100644 --- a/ui/js/component/form.js +++ b/ui/js/component/form.js @@ -1,199 +1,259 @@ import React from 'react'; import FileSelector from './file-selector.js'; -import {Icon} from './common.js'; +import { Icon } from './common.js'; var formFieldCounter = 0, - formFieldFileSelectorTypes = ['file', 'directory'], - formFieldNestedLabelTypes = ['radio', 'checkbox']; + formFieldFileSelectorTypes = ['file', 'directory'], + formFieldNestedLabelTypes = ['radio', 'checkbox']; function formFieldId() { - return "form-field-" + (++formFieldCounter); + return 'form-field-' + ++formFieldCounter; } export class FormField extends React.Component { - static propTypes = { - type: React.PropTypes.string.isRequired, - prefix: React.PropTypes.string, - postfix: React.PropTypes.string, - hasError: React.PropTypes.bool - } + static propTypes = { + type: React.PropTypes.string.isRequired, + prefix: React.PropTypes.string, + postfix: React.PropTypes.string, + hasError: React.PropTypes.bool + }; - constructor(props) { - super(props); + constructor(props) { + super(props); - this._fieldRequiredText = __('This field is required'); - this._type = null; - this._element = null; + this._fieldRequiredText = __('This field is required'); + this._type = null; + this._element = null; - this.state = { - isError: null, - errorMessage: null, - }; - } + this.state = { + isError: null, + errorMessage: null + }; + } - componentWillMount() { - if (['text', 'number', 'radio', 'checkbox'].includes(this.props.type)) { - this._element = 'input'; - this._type = this.props.type; - } else if (this.props.type == 'text-number') { - this._element = 'input'; - this._type = 'text'; - } else if (formFieldFileSelectorTypes.includes(this.props.type)) { - this._element = 'input'; - this._type = 'hidden'; - } else { - // Non field, e.g.