diff --git a/build/downloadDaemon.js b/build/downloadDaemon.js index 4e45f1ad2..4bb955d4e 100644 --- a/build/downloadDaemon.js +++ b/build/downloadDaemon.js @@ -17,7 +17,7 @@ const downloadDaemon = targetPlatform => let currentPlatform = os.platform(); var daemonPlatform = process.env.TARGET || targetPlatform || currentPlatform; - if (daemonPlatform === 'mac' || daemonPlatform === 'darwin') daemonPlatform = 'macos'; + if (daemonPlatform === 'mac' || daemonPlatform === 'darwin') daemonPlatform = 'mac'; if (daemonPlatform === 'win32' || daemonPlatform === 'windows') { daemonPlatform = 'windows'; daemonFileName = daemonFileName + '.exe'; diff --git a/package.json b/package.json index fcb17211c..bbac64b7e 100644 --- a/package.json +++ b/package.json @@ -49,8 +49,8 @@ "formik": "^0.10.4", "hast-util-sanitize": "^1.1.2", "keytar": "^4.2.1", - "lbry-redux": "lbryio/lbry-redux#ecd1ab156fb755c8bff4d890679399d66f41ad17", - "lbryinc": "lbryio/lbryinc#3f34af546ee73ff2ee7d8ad05e540b3b0aa658fb", + "lbry-redux": "lbryio/lbry-redux#634c3899f7d1e01fb08e3bd16d16c66670d6093c", + "lbryinc": "lbryio/lbryinc#3f3aaa9c367765d8ff14a06d0231cc126e94fe96", "localforage": "^1.7.1", "mammoth": "^1.4.6", "mime": "^2.3.1", @@ -134,9 +134,9 @@ "yarn": "^1.3" }, "lbrySettings": { - "lbrynetDaemonVersion": "0.21.2", - "lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip", + "lbrynetDaemonVersion": "0.30.0", + "lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-OSNAME.zip", "lbrynetDaemonDir": "static/daemon", - "lbrynetDaemonFileName": "lbrynet-daemon" + "lbrynetDaemonFileName": "lbrynet" } } diff --git a/src/main/Daemon.js b/src/main/Daemon.js index f530f9768..326c2d92d 100644 --- a/src/main/Daemon.js +++ b/src/main/Daemon.js @@ -3,7 +3,7 @@ import path from 'path'; import { spawn, execSync } from 'child_process'; export default class Daemon { - static path = process.env.LBRY_DAEMON || path.join(__static, 'daemon/lbrynet-daemon'); + static path = process.env.LBRY_DAEMON || path.join(__static, 'daemon/lbrynet'); subprocess; handlers; @@ -12,13 +12,12 @@ export default class Daemon { } launch() { - console.log('Launching daemon:', Daemon.path); - this.subprocess = spawn(Daemon.path); + this.subprocess = spawn(Daemon.path, ['start']); this.subprocess.stdout.on('data', data => console.log(`Daemon: ${data}`)); this.subprocess.stderr.on('data', data => console.error(`Daemon: ${data}`)); this.subprocess.on('exit', () => this.fire('exit')); - this.subprocess.on('error', error => console.error(`Daemon: ${error}`)); + this.subprocess.on('error', error => console.error(`Daemon error: ${error}`)); } quit() { diff --git a/src/main/index.js b/src/main/index.js index 2f19fcd97..91a0d41a3 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -64,8 +64,9 @@ if (isDev) { } app.on('ready', async () => { - const processList = await findProcess('name', 'lbrynet-daemon'); + const processList = await findProcess('name', 'lbrynet'); const isDaemonRunning = processList.length > 0; + if (!isDaemonRunning) { daemon = new Daemon(); daemon.on('exit', () => { @@ -95,11 +96,16 @@ app.on('ready', async () => { // HACK: patch webrequest to fix devtools incompatibility with electron 2.x. // See https://github.com/electron/electron/issues/13008#issuecomment-400261941 session.defaultSession.webRequest.onBeforeRequest({}, (details, callback) => { - if (details.url.indexOf('7accc8730b0f99b5e7c0702ea89d1fa7c17bfe33') !== -1) { - callback({redirectURL: details.url.replace('7accc8730b0f99b5e7c0702ea89d1fa7c17bfe33', '57c9d07b416b5a2ea23d28247300e4af36329bdc')}); - } else { - callback({cancel: false}); - } + if (details.url.indexOf('7accc8730b0f99b5e7c0702ea89d1fa7c17bfe33') !== -1) { + callback({ + redirectURL: details.url.replace( + '7accc8730b0f99b5e7c0702ea89d1fa7c17bfe33', + '57c9d07b416b5a2ea23d28247300e4af36329bdc' + ), + }); + } else { + callback({ cancel: false }); + } }); }); diff --git a/src/renderer/component/fileCard/index.js b/src/renderer/component/fileCard/index.js index b61ae8bb1..626a9a5b0 100644 --- a/src/renderer/component/fileCard/index.js +++ b/src/renderer/component/fileCard/index.js @@ -6,6 +6,7 @@ import { makeSelectFileInfoForUri, makeSelectIsUriResolving, makeSelectClaimIsMine, + makeSelectClaimIsPending, } from 'lbry-redux'; import { doNavigate } from 'redux/actions/navigation'; import { @@ -13,34 +14,22 @@ import { makeSelectContentPositionForUri, } from 'redux/selectors/content'; import { selectShowNsfw } from 'redux/selectors/settings'; -import { selectPendingPublish } from 'redux/selectors/publish'; import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions'; import { doClearContentHistoryUri } from 'redux/actions/content'; import FileCard from './view'; -const select = (state, props) => { - let pendingPublish; - if (props.checkPending) { - pendingPublish = selectPendingPublish(props.uri)(state); - } - - const fileCardInfo = pendingPublish || { - claim: makeSelectClaimForUri(props.uri)(state), - fileInfo: makeSelectFileInfoForUri(props.uri)(state), - metadata: makeSelectMetadataForUri(props.uri)(state), - isResolvingUri: makeSelectIsUriResolving(props.uri)(state), - }; - - return { - obscureNsfw: !selectShowNsfw(state), - claimIsMine: makeSelectClaimIsMine(props.uri)(state), - rewardedContentClaimIds: selectRewardContentClaimIds(state, props), - ...fileCardInfo, - pending: !!pendingPublish, - position: makeSelectContentPositionForUri(props.uri)(state), - isSubscribed: makeSelectIsSubscribed(props.uri)(state), - }; -}; +const select = (state, props) => ({ + pending: makeSelectClaimIsPending(props.uri)(state), + claim: makeSelectClaimForUri(props.uri)(state), + obscureNsfw: !selectShowNsfw(state), + claimIsMine: makeSelectClaimIsMine(props.uri)(state), + rewardedContentClaimIds: selectRewardContentClaimIds(state, props), + fileInfo: makeSelectFileInfoForUri(props.uri)(state), + metadata: makeSelectMetadataForUri(props.uri)(state), + isResolvingUri: makeSelectIsUriResolving(props.uri)(state), + position: makeSelectContentPositionForUri(props.uri)(state), + isSubscribed: makeSelectIsSubscribed(props.uri)(state), +}); const perform = dispatch => ({ navigate: (path, params) => dispatch(doNavigate(path, params)), diff --git a/src/renderer/component/fileList/view.jsx b/src/renderer/component/fileList/view.jsx index 52867ff52..d5bb5e86d 100644 --- a/src/renderer/component/fileList/view.jsx +++ b/src/renderer/component/fileList/view.jsx @@ -10,7 +10,6 @@ type Props = { sortByHeight?: boolean, claimsById: Array<{}>, fileInfos: Array, - checkPending?: boolean, sortBy: string, page?: string, setFileListSort: (?string, string) => void, @@ -30,9 +29,12 @@ class FileList extends React.PureComponent { [SORT_OPTIONS.DATE_NEW]: fileInfos => this.props.sortByHeight ? fileInfos.sort((fileInfo1, fileInfo2) => { - if (fileInfo1.pending) { + if (fileInfo1.confirmations < 1) { return -1; + } else if (fileInfo2.confirmations < 1) { + return 1; } + const height1 = this.props.claimsById[fileInfo1.claim_id] ? this.props.claimsById[fileInfo1.claim_id].height : 0; @@ -125,7 +127,8 @@ class FileList extends React.PureComponent { sortFunctions: {}; render() { - const { fileInfos, hideFilter, checkPending, sortBy } = this.props; + const { fileInfos, hideFilter, sortBy } = this.props; + const content = []; if (!fileInfos) { return null; @@ -151,7 +154,7 @@ class FileList extends React.PureComponent { const outpoint = `${txid}:${nout}`; // See https://github.com/lbryio/lbry-desktop/issues/1327 for discussion around using outpoint as the key - content.push(); + content.push(); }); return ( diff --git a/src/renderer/component/publishForm/view.jsx b/src/renderer/component/publishForm/view.jsx index 91b2300b2..672dbe90c 100644 --- a/src/renderer/component/publishForm/view.jsx +++ b/src/renderer/component/publishForm/view.jsx @@ -123,7 +123,7 @@ class PublishForm extends React.PureComponent { const { channel, updatePublishForm } = this.props; if (!name) { - updatePublishForm({ nameError: undefined }); + updatePublishForm({ name: '', nameError: __('A name is required.') }); return; } diff --git a/src/renderer/component/selectChannel/view.jsx b/src/renderer/component/selectChannel/view.jsx index 01dbb8d41..94e734f13 100644 --- a/src/renderer/component/selectChannel/view.jsx +++ b/src/renderer/component/selectChannel/view.jsx @@ -159,7 +159,6 @@ class ChannelSection extends React.PureComponent { diff --git a/src/renderer/component/uriIndicator/view.jsx b/src/renderer/component/uriIndicator/view.jsx index 85e070ac0..d394850b7 100644 --- a/src/renderer/component/uriIndicator/view.jsx +++ b/src/renderer/component/uriIndicator/view.jsx @@ -38,18 +38,12 @@ class UriIndicator extends React.PureComponent { if (!claim) { return {isResolvingUri ? 'Validating...' : 'Unused'}; } - - const { - channel_name: channelName, - has_signature: hasSignature, - signature_is_valid: signatureIsValid, - value, - } = claim; + const { channel_name: channelName, signature_is_valid: signatureIsValid, value } = claim; const channelClaimId = value && value.publisherSignature && value.publisherSignature.certificateId; - if (!hasSignature || !channelName) { + if (!channelName) { return Anonymous; } diff --git a/src/renderer/component/walletSendTip/index.js b/src/renderer/component/walletSendTip/index.js index ad1d98cb7..57f4c5d28 100644 --- a/src/renderer/component/walletSendTip/index.js +++ b/src/renderer/component/walletSendTip/index.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import { - doSendSupport, + doSendTip, makeSelectTitleForUri, makeSelectClaimForUri, selectIsSendingSupport, @@ -16,7 +16,10 @@ const select = (state, props) => ({ }); const perform = dispatch => ({ - sendSupport: (amount, claimId, uri) => dispatch(doSendSupport(amount, claimId, uri)), + sendSupport: (amount, claimId, uri) => dispatch(doSendTip(amount, claimId, uri)), }); -export default connect(select, perform)(WalletSendTip); +export default connect( + select, + perform +)(WalletSendTip); diff --git a/src/renderer/page/fileListPublished/index.js b/src/renderer/page/fileListPublished/index.js index 871c44ed5..d3b4e90fd 100644 --- a/src/renderer/page/fileListPublished/index.js +++ b/src/renderer/page/fileListPublished/index.js @@ -1,20 +1,19 @@ import { connect } from 'react-redux'; -import { selectPendingPublishes, selectClaimsWithPendingPublishes } from 'redux/selectors/publish'; -import { selectIsFetchingClaimListMine, selectFileListPublishedSort } from 'lbry-redux'; +import { selectPendingPublishes } from 'redux/selectors/publish'; +import { selectIsFetchingClaimListMine, selectFileListPublishedSort, selectMyClaimsWithoutChannels } from 'lbry-redux'; import { doNavigate } from 'redux/actions/navigation'; import { doCheckPendingPublishes } from 'redux/actions/publish'; import FileListPublished from './view'; const select = state => ({ - claims: selectClaimsWithPendingPublishes(state), + claims: selectMyClaimsWithoutChannels(state), fetching: selectIsFetchingClaimListMine(state), - pendingPublishes: selectPendingPublishes(state), sortBy: selectFileListPublishedSort(state), }); const perform = dispatch => ({ navigate: path => dispatch(doNavigate(path)), - checkIfPublishesConfirmed: publishes => dispatch(doCheckPendingPublishes(publishes)), + checkPendingPublishes: () => dispatch(doCheckPendingPublishes()), }); export default connect( diff --git a/src/renderer/page/fileListPublished/view.jsx b/src/renderer/page/fileListPublished/view.jsx index d25fb8c9b..338da3b60 100644 --- a/src/renderer/page/fileListPublished/view.jsx +++ b/src/renderer/page/fileListPublished/view.jsx @@ -1,4 +1,5 @@ // @flow +import type { Claim } from 'types/claim'; import React from 'react'; import Button from 'component/button'; import FileList from 'component/fileList'; @@ -6,9 +7,8 @@ import Page from 'component/page'; import { PAGES } from 'lbry-redux'; type Props = { - pendingPublishes: Array<{}>, - claims: Array<{}>, - checkIfPublishesConfirmed: (Array<{}>) => void, + claims: Array, + checkPendingPublishes: () => void, navigate: (string, ?{}) => void, fetching: boolean, sortBy: string, @@ -16,10 +16,8 @@ type Props = { class FileListPublished extends React.PureComponent { componentDidMount() { - const { pendingPublishes, checkIfPublishesConfirmed } = this.props; - if (pendingPublishes.length) { - checkIfPublishesConfirmed(pendingPublishes); - } + const { checkPendingPublishes } = this.props; + checkPendingPublishes(); } render() { diff --git a/src/renderer/page/help/view.jsx b/src/renderer/page/help/view.jsx index 4bd07428a..52c22a2c8 100644 --- a/src/renderer/page/help/view.jsx +++ b/src/renderer/page/help/view.jsx @@ -26,7 +26,6 @@ type VersionInfo = { os_release: string, platform: string, lbrynet_version: string, - lbryum_version: string, }; type State = { @@ -209,10 +208,6 @@ class HelpPage extends React.PureComponent { {__('Daemon (lbrynet)')} {ver.lbrynet_version} - - {__('Wallet (lbryum)')} - {ver.lbryum_version} - {__('Connected Email')} diff --git a/src/renderer/redux/actions/content.js b/src/renderer/redux/actions/content.js index 5a07c8ad7..81fdcecda 100644 --- a/src/renderer/redux/actions/content.js +++ b/src/renderer/redux/actions/content.js @@ -292,7 +292,7 @@ export function doFetchClaimsByChannel(uri, page, pageSize) { data: { uri, page }, }); - Lbry.claim_list_by_channel({ uri, page: page || 1, page_size: pageSize || 48 }).then(result => { + Lbry.claim_list_by_channel({ uri, page: page || 1, page_size: pageSize || 20 }).then(result => { const claimResult = result[uri] || {}; const { claims_in_channel: claimsInChannel, returned_page: returnedPage } = claimResult; diff --git a/src/renderer/redux/actions/publish.js b/src/renderer/redux/actions/publish.js index ca831c214..af0e9709a 100644 --- a/src/renderer/redux/actions/publish.js +++ b/src/renderer/redux/actions/publish.js @@ -1,4 +1,11 @@ // @flow +import type { Dispatch, GetState } from 'types/redux'; +import type { Source, Metadata } from 'types/claim'; +import type { + UpdatePublishFormData, + UpdatePublishFormAction, + PublishParams, +} from 'redux/reducers/publish'; import { ACTIONS, Lbry, @@ -7,20 +14,14 @@ import { selectMyChannelClaims, THUMBNAIL_STATUSES, batchActions, + creditsToString, + selectPendingById, } from 'lbry-redux'; -import { selectPendingPublishes } from 'redux/selectors/publish'; -import type { - UpdatePublishFormData, - UpdatePublishFormAction, - PublishParams, -} from 'redux/reducers/publish'; import { selectosNotificationsEnabled } from 'redux/selectors/settings'; import { doNavigate } from 'redux/actions/navigation'; import fs from 'fs'; import path from 'path'; import { CC_LICENSES, COPYRIGHT, OTHER } from 'constants/licenses'; -import type { Dispatch, GetState } from 'types/redux'; -import type { Source } from 'types/claim'; type Action = UpdatePublishFormAction | { type: ACTIONS.CLEAR_PUBLISH }; @@ -229,7 +230,6 @@ export const doPublish = (params: PublishParams) => ( licenseUrl, language, thumbnail, - fee: fee || undefined, description: description || undefined, }; @@ -237,16 +237,23 @@ export const doPublish = (params: PublishParams) => ( name: ?string, channel_id: string, bid: ?number, - metadata: ?any, + metadata: ?Metadata, file_path?: string, sources?: Source, } = { name, channel_id: channelId, - bid, + bid: creditsToString(bid), metadata, }; + if (fee) { + metadata.fee = { + currency: fee.currency, + amount: creditsToString(fee.amount), + }; + } + if (filePath) { publishPayload.file_path = filePath; } else { @@ -258,7 +265,6 @@ export const doPublish = (params: PublishParams) => ( const success = () => { dispatch({ type: ACTIONS.PUBLISH_SUCCESS, - data: { pendingPublish: { ...publishPayload } }, }); dispatch(doNotify({ id: MODALS.PUBLISH }, { uri })); }; @@ -274,28 +280,21 @@ export const doPublish = (params: PublishParams) => ( // Calls claim_list_mine until any pending publishes are confirmed export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetState) => { const state = getState(); - const pendingPublishes = selectPendingPublishes(state); + const pendingById = selectPendingById(state); + if (!Object.keys(pendingById)) { + return; + } let publishCheckInterval; const checkFileList = () => { Lbry.claim_list_mine().then(claims => { - const pendingPublishMap = {}; - pendingPublishes.forEach(({ name }) => { - pendingPublishMap[name] = name; - }); - - const actions = []; claims.forEach(claim => { - if (pendingPublishMap[claim.name]) { - actions.push({ - type: ACTIONS.REMOVE_PENDING_PUBLISH, - data: { - name: claim.name, - }, - }); + // If it's confirmed, check that it wasn't pending previously + if (claim.confirmations > 0 && pendingById[claim.claim_id]) { + delete pendingById[claim.claim_id]; - delete pendingPublishMap[claim.name]; + // If it's confirmed, check if we should notify the user if (selectosNotificationsEnabled(getState())) { const notif = new window.Notification('LBRY Publish Complete', { body: `${claim.value.stream.metadata.title} has been published to lbry://${ @@ -314,25 +313,21 @@ export const doCheckPendingPublishes = () => (dispatch: Dispatch, getSta } }); - actions.push({ + dispatch({ type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED, data: { claims, }, }); - dispatch(batchActions(...actions)); - - if (!Object.keys(pendingPublishMap).length) { + if (!Object.keys(pendingById).length) { clearInterval(publishCheckInterval); } }); }; - if (pendingPublishes.length) { + checkFileList(); + publishCheckInterval = setInterval(() => { checkFileList(); - publishCheckInterval = setInterval(() => { - checkFileList(); - }, 30000); - } + }, 30000); }; diff --git a/src/renderer/redux/actions/subscriptions.js b/src/renderer/redux/actions/subscriptions.js index ab03efe8d..5ad5ba103 100644 --- a/src/renderer/redux/actions/subscriptions.js +++ b/src/renderer/redux/actions/subscriptions.js @@ -100,7 +100,7 @@ export const doFetchMySubscriptions = () => (dispatch: ReduxDispatch, getState: data: subscriptions, }); - subscriptions.forEach(({ uri }) => dispatch(doFetchClaimsByChannel(uri, 1, 20))); + subscriptions.forEach(({ uri }) => dispatch(doFetchClaimsByChannel(uri, 1))); }) .catch(() => { dispatch({ diff --git a/src/renderer/redux/reducers/publish.js b/src/renderer/redux/reducers/publish.js index 53e20375c..e32fe1814 100644 --- a/src/renderer/redux/reducers/publish.js +++ b/src/renderer/redux/reducers/publish.js @@ -29,7 +29,6 @@ type PublishState = { bidError: ?string, otherLicenseDescription: string, licenseUrl: string, - pendingPublishes: Array, }; export type UpdatePublishFormData = { @@ -115,7 +114,6 @@ const defaultState: PublishState = { publishing: false, publishSuccess: false, publishError: undefined, - pendingPublishes: [], }; export default handleActions( @@ -127,10 +125,9 @@ export default handleActions( ...data, }; }, - [ACTIONS.CLEAR_PUBLISH]: (state: PublishState): PublishState => { - const { pendingPublishes } = state; - return { ...defaultState, pendingPublishes }; - }, + [ACTIONS.CLEAR_PUBLISH]: (): PublishState => ({ + ...defaultState, + }), [ACTIONS.PUBLISH_START]: (state: PublishState): PublishState => ({ ...state, publishing: true, @@ -139,29 +136,11 @@ export default handleActions( ...state, publishing: false, }), - [ACTIONS.PUBLISH_SUCCESS]: (state: PublishState, action): PublishState => { - const { pendingPublish } = action.data; - - const newPendingPublishes = state.pendingPublishes.slice(); - - newPendingPublishes.push(pendingPublish); - - return { - ...state, - publishing: false, - pendingPublishes: newPendingPublishes, - }; - }, - [ACTIONS.REMOVE_PENDING_PUBLISH]: (state: PublishState, action) => { - const { name } = action.data; - const pendingPublishes = state.pendingPublishes.filter(publish => publish.name !== name); - return { - ...state, - pendingPublishes, - }; - }, + [ACTIONS.PUBLISH_SUCCESS]: (state: PublishState): PublishState => ({ + ...state, + publishing: false, + }), [ACTIONS.DO_PREPARE_EDIT]: (state: PublishState, action) => { - const { pendingPublishes } = state; const { ...publishData } = action.data; const { channel, name, uri } = publishData; @@ -175,7 +154,6 @@ export default handleActions( return { ...defaultState, ...publishData, - pendingPublishes, editingURI: uri, uri: shortUri, }; diff --git a/src/renderer/redux/selectors/publish.js b/src/renderer/redux/selectors/publish.js index 0d3c72bd5..536809f28 100644 --- a/src/renderer/redux/selectors/publish.js +++ b/src/renderer/redux/selectors/publish.js @@ -10,47 +10,11 @@ import { const selectState = state => state.publish || {}; -export const selectPendingPublishes = createSelector( - selectState, - state => state.pendingPublishes.map(pendingClaim => ({ ...pendingClaim, pending: true })) || [] -); - -export const selectClaimsWithPendingPublishes = createSelector( - selectMyClaimsWithoutChannels, - selectPendingPublishes, - (claims, pendingPublishes) => { - // ensure there are no duplicates, they are being checked for in a setInterval - // no need to wait for it to complete though - // loop through myclaims - // if a claim has the same name as one in pendingPublish, remove it from pending - const claimMap = {}; - claims.forEach(claim => { - claimMap[claim.name] = true; - }); - - const filteredPendingPublishes = pendingPublishes.filter(claim => !claimMap[claim.name]); - return [...filteredPendingPublishes, ...claims]; - } -); - export const selectPublishFormValues = createSelector(selectState, state => { const { pendingPublish, ...formValues } = state; return formValues; }); -export const selectPendingPublish = uri => - createSelector(selectPendingPublishes, pendingPublishes => { - const { claimName, contentName } = parseURI(uri); - - if (!pendingPublishes.length) { - return null; - } - - return pendingPublishes.filter( - publish => publish.name === claimName || publish.name === contentName - )[0]; - }); - // Is the current uri the same as the uri they clicked "edit" on export const selectIsStillEditing = createSelector(selectPublishFormValues, publishState => { const { editingURI, uri } = publishState; diff --git a/src/renderer/util/formatCredits.js b/src/renderer/util/formatCredits.js index 98383c05f..339ea3c42 100644 --- a/src/renderer/util/formatCredits.js +++ b/src/renderer/util/formatCredits.js @@ -1,5 +1,7 @@ -export function formatCredits(amount, precision) { - return amount.toFixed(precision || 1).replace(/\.?0+$/, ''); +export function formatCredits(amount, precision = 1) { + return parseFloat(amount) + .toFixed(precision || 1) + .replace(/\.?0+$/, ''); } export function formatFullPrice(amount, precision = 1) { diff --git a/yarn.lock b/yarn.lock index 208228689..8007cf0bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5663,25 +5663,18 @@ lazy-val@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc" -lbry-redux@lbryio/lbry-redux: +lbry-redux@lbryio/lbry-redux#634c3899f7d1e01fb08e3bd16d16c66670d6093c: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/a8e81949837171e94e649fce6f7c7a8b7faadd51" + resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/634c3899f7d1e01fb08e3bd16d16c66670d6093c" dependencies: proxy-polyfill "0.1.6" reselect "^3.0.0" -lbry-redux@lbryio/lbry-redux#03aea43da5f12bc01546a92bdf460ebd08681013: +lbryinc@lbryio/lbryinc#3f3aaa9c367765d8ff14a06d0231cc126e94fe96: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/03aea43da5f12bc01546a92bdf460ebd08681013" + resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/3f3aaa9c367765d8ff14a06d0231cc126e94fe96" dependencies: - proxy-polyfill "0.1.6" - reselect "^3.0.0" - -lbryinc@lbryio/lbryinc#3f34af546ee73ff2ee7d8ad05e540b3b0aa658fb: - version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/3f34af546ee73ff2ee7d8ad05e540b3b0aa658fb" - dependencies: - lbry-redux lbryio/lbry-redux + lbry-redux lbryio/lbry-redux#634c3899f7d1e01fb08e3bd16d16c66670d6093c reselect "^3.0.0" lcid@^1.0.0: