diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..020651d28 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,36 @@ +## PR Checklist +Please check all that apply to this PR using "x": + +- [ ] I have checked that this PR is not a duplicate of an existing PR (open, closed or merged) +- [ ] I have checked that this PR does not introduce a breaking change +- [ ] This PR introduces breaking changes and I have provided a detailed explanation below + + +## PR Type +What kind of change does this PR introduce? + + + +- [ ] Bugfix +- [ ] Feature +- [ ] Breaking changes (bugfix or feature that introduces breaking changes) +- [ ] Code style update (formatting) +- [ ] Refactoring (no functional changes) +- [ ] Documentation changes +- [ ] Other - Please describe: + +## Fixes + +Issue Number: N/A + + +## What is the current behavior? + + +## What is the new behavior? + + +## Other information + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a97a6e4a..ef87b8f3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * Adds Persistence to File List Filter Selections ([#2050](https://github.com/lbryio/lbry-desktop/pull/2050)) ### Changed + * Upgraded to lbrynet v0.30.0 ([#1998](https://github.com/lbryio/lbry-desktop/pull/1998)) * Make tooltip smarter ([#1979](https://github.com/lbryio/lbry-desktop/pull/1979)) * Change channel pages to have 48 items instead of 10 ([#2002](https://github.com/lbryio/lbry-desktop/pull/2002)) * Update to https ([#2016](https://github.com/lbryio/lbry-desktop/pull/2016)) @@ -96,6 +97,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * Fix middle click link error ([#1843](https://github.com/lbryio/lbry-desktop/issues/1843)} * Problem with search auto-complete menu when scrolling over file viewer ([#1847](https://github.com/lbryio/lbry-desktop/issues/1847)) * Show label when publish button is disabled while uploading thumbnail to spee.ch ([#1867](https://github.com/lbryio/lbry-desktop/pull/1867)) + * Edit option missing from certain published claims ([#1756](https://github.com/lbryio/lbry-desktop/issues/1756)) + * Navigation issue with channels that have more than one page ([#1797](https://github.com/lbryio/lbry-desktop/pull/1797)) + * Navigation issue with channels that have more than one page ([#1797](https://github.com/lbryio/lbry-desktop/pull/1797)) + * Upgrade modals would stack on-top of each other if the app was kept open for a long time ([#1857](https://github.com/lbryio/lbry-desktop/pull/1857)) ### Added * 3D file viewer for OBJ & STL file types ([#1558](https://github.com/lbryio/lbry-desktop/pull/1558)) @@ -114,14 +119,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * More descriptive error message when Shapeshift is unavailable ([#1771](https://github.com/lbryio/lbry-desktop/pull/1771)) * Rename the Github repo to lbry-desktop ([#1765](https://github.com/lbryio/lbry-desktop/pull/1765)) - -### Fixed - * Edit option missing from certain published claims ([#1756](https://github.com/lbryio/lbry-desktop/issues/1756)) - * Navigation issue with channels that have more than one page ([#1797](https://github.com/lbryio/lbry-desktop/pull/1797)) - * Navigation issue with channels that have more than one page ([#1797](https://github.com/lbryio/lbry-desktop/pull/1797)) - * Upgrade modals would stack on-top of each other if the app was kept open for a long time ([#1857](https://github.com/lbryio/lbry-desktop/pull/1857)) - - ## [0.22.2] - 2018-07-09 ### Fixed diff --git a/README.md b/README.md index c927a221e..76ffec921 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # LBRY App +[![MIT licensed](https://img.shields.io/dub/l/vibe-d.svg?style=flat)](https://github.com/lbryio/lbry-desktop/blob/master/LICENSE) [![Build Status](https://travis-ci.org/lbryio/lbry-desktop.svg?branch=master)](https://travis-ci.org/lbryio/lbry-desktop) [![Dependencies](https://david-dm.org/lbryio/lbry-desktop/status.svg)](https://david-dm.org/lbryio/lbry-desktop) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/78b627d4f5524792adc48719835e1523)](https://www.codacy.com/app/LBRY/lbry-desktop?utm_source=github.com&utm_medium=referral&utm_content=lbryio/lbry-desktop&utm_campaign=Badge_Grade) 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 0dce4c7e0..0787f6304 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#03aea43da5f12bc01546a92bdf460ebd08681013", - "lbryinc": "lbryio/lbryinc#3f34af546ee73ff2ee7d8ad05e540b3b0aa658fb", + "lbry-redux": "lbryio/lbry-redux#f193d38c61ea061679ebc7b4ca139a0e9c95ef8a", + "lbryinc": "lbryio/lbryinc#7a458ea13ceceffa0191e73139f94e5c953f22b1", "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/address/index.js b/src/renderer/component/address/index.js index 9aaa4a3bc..e38b68ada 100644 --- a/src/renderer/component/address/index.js +++ b/src/renderer/component/address/index.js @@ -1,7 +1,12 @@ +// @flow + import { connect } from 'react-redux'; import { doNotify } from 'lbry-redux'; import Address from './view'; -export default connect(null, { - doNotify, -})(Address); +export default connect( + null, + { + doNotify, + } +)(Address); diff --git a/src/renderer/component/cardMedia/index.js b/src/renderer/component/cardMedia/index.js index 1f7988712..22c6c0488 100644 --- a/src/renderer/component/cardMedia/index.js +++ b/src/renderer/component/cardMedia/index.js @@ -1,8 +1,3 @@ -import React from 'react'; -import { connect } from 'react-redux'; import CardMedia from './view'; -const select = state => ({}); -const perform = dispatch => ({}); - -export default connect(select, perform)(CardMedia); +export default CardMedia; 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 b2b1eaa45..d5bb5e86d 100644 --- a/src/renderer/component/fileList/view.jsx +++ b/src/renderer/component/fileList/view.jsx @@ -10,15 +10,15 @@ type Props = { sortByHeight?: boolean, claimsById: Array<{}>, fileInfos: Array, - checkPending?: boolean, sortBy: string, - page: string, - setFileListSort: (string, string) => void, + page?: string, + setFileListSort: (?string, string) => void, }; class FileList extends React.PureComponent { static defaultProps = { hideFilter: false, + sortBy: SORT_OPTIONS.DATE_NEW, }; constructor(props: Props) { @@ -29,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; @@ -124,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; @@ -150,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/fileListSearch/index.js b/src/renderer/component/fileListSearch/index.js index 5f4011e2d..351776461 100644 --- a/src/renderer/component/fileListSearch/index.js +++ b/src/renderer/component/fileListSearch/index.js @@ -8,9 +8,4 @@ const select = (state, props) => ({ isSearching: selectIsSearching(state), }); -const perform = () => ({}); - -export default connect( - select, - perform -)(FileListSearch); +export default connect(select)(FileListSearch); diff --git a/src/renderer/component/formFieldPrice/index.js b/src/renderer/component/formFieldPrice/index.js index c3dea1781..050c3d310 100644 --- a/src/renderer/component/formFieldPrice/index.js +++ b/src/renderer/component/formFieldPrice/index.js @@ -1,5 +1,3 @@ -import React from 'react'; -import { connect } from 'react-redux'; import FormFieldPrice from './view'; -export default connect(null, null)(FormFieldPrice); +export default FormFieldPrice; diff --git a/src/renderer/component/publishForm/index.js b/src/renderer/component/publishForm/index.js index dfb124897..6b0644544 100644 --- a/src/renderer/component/publishForm/index.js +++ b/src/renderer/component/publishForm/index.js @@ -1,5 +1,3 @@ -import { connect } from 'react-redux'; -import { selectBalance } from 'lbry-redux'; import PublishForm from './view'; -export default connect(null, null)(PublishForm); +export default PublishForm; 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/shapeShift/internal/active-shift.jsx b/src/renderer/component/shapeShift/internal/active-shift.jsx index 373017b81..fd14d27a1 100644 --- a/src/renderer/component/shapeShift/internal/active-shift.jsx +++ b/src/renderer/component/shapeShift/internal/active-shift.jsx @@ -5,18 +5,20 @@ import { FormRow } from 'component/common/form'; import * as statuses from 'constants/shape_shift'; import Address from 'component/address'; import Button from 'component/button'; -import type { Dispatch } from 'redux/actions/shape_shift'; +import type { Dispatch, ThunkAction } from 'types/redux'; +import type { Action } from 'redux/actions/shape_shift'; + import ShiftMarketInfo from './market_info'; type Props = { shiftState: ?string, shiftCoinType: ?string, - shiftDepositAddress: ?string, + shiftDepositAddress: string, shiftReturnAddress: ?string, shiftOrderId: ?string, originCoinDepositMax: ?number, - clearShapeShift: Dispatch, - getActiveShift: Dispatch, + clearShapeShift: () => (Dispatch) => ThunkAction, + getActiveShift: string => (Dispatch) => ThunkAction, shapeShiftRate: ?number, originCoinDepositMax: ?number, originCoinDepositFee: ?number, diff --git a/src/renderer/component/shapeShift/internal/form.jsx b/src/renderer/component/shapeShift/internal/form.jsx index f4d057527..9f635d8ab 100644 --- a/src/renderer/component/shapeShift/internal/form.jsx +++ b/src/renderer/component/shapeShift/internal/form.jsx @@ -2,7 +2,8 @@ import React from 'react'; import { getExampleAddress } from 'util/shape_shift'; import { FormField, FormRow, Submit } from 'component/common/form'; -import type { ShapeShiftFormValues, Dispatch } from 'redux/actions/shape_shift'; +import type { ShapeShiftFormValues, Action } from 'redux/actions/shape_shift'; +import type { Dispatch, ThunkAction } from 'types/redux'; import ShiftMarketInfo from './market_info'; type ShapeShiftFormErrors = { @@ -19,7 +20,7 @@ type Props = { isSubmitting: boolean, shiftSupportedCoins: Array, originCoin: string, - getCoinStats: Dispatch, + getCoinStats: string => (Dispatch) => ThunkAction, originCoinDepositFee: number, originCoinDepositMin: string, originCoinDepositMax: number, diff --git a/src/renderer/component/shapeShift/view.jsx b/src/renderer/component/shapeShift/view.jsx index 7faefe4bd..8074ce8c0 100644 --- a/src/renderer/component/shapeShift/view.jsx +++ b/src/renderer/component/shapeShift/view.jsx @@ -4,17 +4,23 @@ import { Formik } from 'formik'; import { validateShapeShiftForm } from 'util/shape_shift'; import Button from 'component/button'; import type { ShapeShiftState } from 'redux/reducers/shape_shift'; -import type { Dispatch, ShapeShiftFormValues } from 'redux/actions/shape_shift'; +import type { ShapeShiftFormValues, Action } from 'redux/actions/shape_shift'; +import type { Dispatch, ThunkAction } from 'types/redux'; +import type { FormikActions } from 'types/common'; + import ShapeShiftForm from './internal/form'; import ActiveShapeShift from './internal/active-shift'; type Props = { shapeShift: ShapeShiftState, - getCoinStats: Dispatch, - createShapeShift: Dispatch, - clearShapeShift: Dispatch, - getActiveShift: Dispatch, - shapeShiftInit: Dispatch, + getCoinStats: string => (Dispatch) => ThunkAction, + createShapeShift: ( + ShapeShiftFormValues, + FormikActions + ) => (Dispatch) => ThunkAction, + clearShapeShift: () => (Dispatch) => ThunkAction, + getActiveShift: string => (Dispatch) => ThunkAction, + shapeShiftInit: () => (Dispatch) => ThunkAction, receiveAddress: string, }; @@ -42,7 +48,6 @@ class ShapeShift extends React.PureComponent { } = this.props; const { - loading, updating, error, shiftSupportedCoins, @@ -104,7 +109,7 @@ class ShapeShift extends React.PureComponent { getActiveShift={getActiveShift} shiftCoinType={shiftCoinType} shiftReturnAddress={shiftReturnAddress} - shiftDepositAddress={shiftDepositAddress} + shiftDepositAddress={shiftDepositAddress || ''} shiftOrderId={shiftOrderId} shiftState={shiftState} clearShapeShift={clearShapeShift} diff --git a/src/renderer/component/theme/index.js b/src/renderer/component/theme/index.js index 77f5fba6d..cb4fc92c9 100644 --- a/src/renderer/component/theme/index.js +++ b/src/renderer/component/theme/index.js @@ -1,10 +1,9 @@ -import React from 'react'; import { connect } from 'react-redux'; -import { selectThemePath } from 'redux/selectors/settings.js'; +import { selectThemePath } from 'redux/selectors/settings'; import Theme from './view'; const select = state => ({ themePath: selectThemePath(state), }); -export default connect(select, null)(Theme); +export default connect(select)(Theme); 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/walletAddress/view.jsx b/src/renderer/component/walletAddress/view.jsx index 50f43dd34..73b932736 100644 --- a/src/renderer/component/walletAddress/view.jsx +++ b/src/renderer/component/walletAddress/view.jsx @@ -12,19 +12,19 @@ type Props = { gettingNewAddress: boolean, }; -class WalletAddress extends React.PureComponent { +type State = { + showQR: boolean, +}; + +class WalletAddress extends React.PureComponent { constructor(props: Props) { super(props); this.state = { showQR: false, }; - } - toggleQR() { - this.setState({ - showQR: !this.state.showQR, - }); + this.toggleQR = this.toggleQR.bind(this); } componentWillMount() { @@ -36,6 +36,14 @@ class WalletAddress extends React.PureComponent { } } + toggleQR: Function; + + toggleQR() { + this.setState({ + showQR: !this.state.showQR, + }); + } + render() { const { receiveAddress, getNewAddress, gettingNewAddress } = this.props; const { showQR } = this.state; @@ -62,7 +70,7 @@ class WalletAddress extends React.PureComponent {