From 6c4a4e593c26ed7eae9356cf9b8a03933b90542c Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Wed, 20 Dec 2017 18:38:11 -0500 Subject: [PATCH 01/52] track and manage video state --- .../component/fileDownloadLink/index.js | 4 +- .../component/fileDownloadLink/view.jsx | 4 +- src/renderer/component/video/index.js | 17 ++++++-- .../component/video/internal/player.jsx | 24 +++++++++--- src/renderer/component/video/view.jsx | 16 ++++++-- src/renderer/constants/action_types.js | 5 +++ src/renderer/redux/actions/media.js | 31 +++++++++++++++ src/renderer/redux/reducers/media.js | 39 +++++++++++++++++++ src/renderer/redux/selectors/media.js | 15 +++++++ src/renderer/store.js | 2 + 10 files changed, 140 insertions(+), 17 deletions(-) create mode 100644 src/renderer/redux/actions/media.js create mode 100644 src/renderer/redux/reducers/media.js create mode 100644 src/renderer/redux/selectors/media.js diff --git a/src/renderer/component/fileDownloadLink/index.js b/src/renderer/component/fileDownloadLink/index.js index e35dc5b94..edc52cffc 100644 --- a/src/renderer/component/fileDownloadLink/index.js +++ b/src/renderer/component/fileDownloadLink/index.js @@ -9,7 +9,7 @@ import { makeSelectCostInfoForUri } from "redux/selectors/cost_info"; import { doFetchAvailability } from "redux/actions/availability"; import { doOpenFileInShell } from "redux/actions/file_info"; import { doPurchaseUri, doStartDownload } from "redux/actions/content"; -import { setVideoPause } from "redux/actions/video"; +import { doPause } from "redux/actions/media"; import FileDownloadLink from "./view"; const select = (state, props) => ({ @@ -25,7 +25,7 @@ const perform = dispatch => ({ openInShell: path => dispatch(doOpenFileInShell(path)), purchaseUri: uri => dispatch(doPurchaseUri(uri)), restartDownload: (uri, outpoint) => dispatch(doStartDownload(uri, outpoint)), - setVideoPause: val => dispatch(setVideoPause(val)), + doPause: () => dispatch(doPause()), }); export default connect(select, perform)(FileDownloadLink); diff --git a/src/renderer/component/fileDownloadLink/view.jsx b/src/renderer/component/fileDownloadLink/view.jsx index 0619460dd..d2349059b 100644 --- a/src/renderer/component/fileDownloadLink/view.jsx +++ b/src/renderer/component/fileDownloadLink/view.jsx @@ -42,12 +42,12 @@ class FileDownloadLink extends React.PureComponent { purchaseUri, costInfo, loading, - setVideoPause, + doPause, } = this.props; const openFile = () => { openInShell(fileInfo.download_path); - setVideoPause(true); + doPause(); }; if (loading || downloading) { diff --git a/src/renderer/component/video/index.js b/src/renderer/component/video/index.js index f0a1a43f1..bec9e46b6 100644 --- a/src/renderer/component/video/index.js +++ b/src/renderer/component/video/index.js @@ -3,7 +3,8 @@ import { connect } from "react-redux"; import { doChangeVolume } from "redux/actions/app"; import { selectVolume } from "redux/selectors/app"; import { doPlayUri, doSetPlayingUri } from "redux/actions/content"; -import { setVideoPause } from "redux/actions/video"; +import { doPlay, doPause, savePosition } from "redux/actions/media"; +// import { setVideoPause } from "redux/actions/video"; import { makeSelectMetadataForUri, makeSelectContentTypeForUri, @@ -15,7 +16,11 @@ import { } from "redux/selectors/file_info"; import { makeSelectCostInfoForUri } from "redux/selectors/cost_info"; import { selectShowNsfw } from "redux/selectors/settings"; -import { selectVideoPause } from "redux/selectors/video"; +// import { selectVideoPause } from "redux/selectors/video"; +import { + selectMediaPaused, + makeSelectMediaPositionForUri, +} from "redux/selectors/media"; import Video from "./view"; import { selectPlayingUri } from "redux/selectors/content"; @@ -29,14 +34,18 @@ const select = (state, props) => ({ playingUri: selectPlayingUri(state), contentType: makeSelectContentTypeForUri(props.uri)(state), volume: selectVolume(state), - videoPause: selectVideoPause(state), + // videoPause: selectVideoPause(state), + mediaPaused: selectMediaPaused(state), + mediaPosition: makeSelectMediaPositionForUri(props.uri)(state), }); const perform = dispatch => ({ play: uri => dispatch(doPlayUri(uri)), cancelPlay: () => dispatch(doSetPlayingUri(null)), changeVolume: volume => dispatch(doChangeVolume(volume)), - setVideoPause: val => dispatch(setVideoPause(val)), + // setVideoPause: val => dispatch(setVideoPause(val)), + doPlay: () => dispatch(doPlay()), + doPause: (id, position) => dispatch(doPause(id, position)), }); export default connect(select, perform)(Video); diff --git a/src/renderer/component/video/internal/player.jsx b/src/renderer/component/video/internal/player.jsx index e993dac36..c0e13acab 100644 --- a/src/renderer/component/video/internal/player.jsx +++ b/src/renderer/component/video/internal/player.jsx @@ -20,11 +20,10 @@ class VideoPlayer extends React.PureComponent { this.togglePlayListener = this.togglePlay.bind(this); } - componentWillReceiveProps(nextProps) { - if (nextProps.videoPause) { - this.refs.media.children[0].pause(); - this.props.setVideoPause(false); - } + componentWillReceiveProps(next) { + const el = this.refs.media.children[0]; + if (!this.props.paused && next.paused && !el.paused) el.pause(); + // if (this.props.paused && !next.paused && el.paused) el.play(); } componentDidMount() { @@ -35,7 +34,15 @@ class VideoPlayer extends React.PureComponent { mediaType, changeVolume, volume, + mediaId, + position, } = this.props; + + // I'm using a Timeout because I'm not sure where this should happen + if (position > 0) { + setTimeout(() => (mediaElement.currentTime = position), 900); + } + const loadedMetadata = e => { this.setState({ hasMetadata: true, startedPlaying: true }); this.refs.media.children[0].play(); @@ -68,6 +75,11 @@ class VideoPlayer extends React.PureComponent { document.addEventListener("keydown", this.togglePlayListener); const mediaElement = this.refs.media.children[0]; if (mediaElement) { + mediaElement.addEventListener("play", () => this.props.doPlay()); + mediaElement.addEventListener("pause", () => { + console.log("CURRENT TIME:", mediaElement.currentTime); + this.props.doPause(this.props.mediaId, mediaElement.currentTime); + }); mediaElement.addEventListener("click", this.togglePlayListener); mediaElement.addEventListener( "loadedmetadata", @@ -92,7 +104,9 @@ class VideoPlayer extends React.PureComponent { const mediaElement = this.refs.media.children[0]; if (mediaElement) { mediaElement.removeEventListener("click", this.togglePlayListener); + //mediaElement.removeEventListener("play"); ?? } + this.props.doPause(this.props.mediaId, mediaElement.currentTime); } renderAudio(container, autoplay) { diff --git a/src/renderer/component/video/view.jsx b/src/renderer/component/video/view.jsx index c5c4d8d88..9f793b783 100644 --- a/src/renderer/component/video/view.jsx +++ b/src/renderer/component/video/view.jsx @@ -56,8 +56,10 @@ class Video extends React.PureComponent { changeVolume, volume, uri, - videoPause, - setVideoPause, + doPlay, + doPause, + mediaPaused, + mediaPosition, } = this.props; const isPlaying = playingUri === uri; @@ -93,6 +95,9 @@ class Video extends React.PureComponent { } const poster = metadata.thumbnail; + const mediaId = uri.split("#")[1]; + console.log("mediaId:", mediaId); + return (
))} {!isPlaying && ( diff --git a/src/renderer/constants/action_types.js b/src/renderer/constants/action_types.js index bbf6c520b..774a48559 100644 --- a/src/renderer/constants/action_types.js +++ b/src/renderer/constants/action_types.js @@ -167,3 +167,8 @@ export const HAS_FETCHED_SUBSCRIPTIONS = "HAS_FETCHED_SUBSCRIPTIONS"; // Video controls export const SET_VIDEO_PAUSE = "SET_VIDEO_PAUSE"; + +// Media controls +export const MEDIA_PLAY = "MEDIA_PLAY"; +export const MEDIA_PAUSE = "MEDIA_PAUSE"; +export const MEDIA_POSITION = "MEDIA_POSITION"; diff --git a/src/renderer/redux/actions/media.js b/src/renderer/redux/actions/media.js new file mode 100644 index 000000000..2ee20e3fa --- /dev/null +++ b/src/renderer/redux/actions/media.js @@ -0,0 +1,31 @@ +// @flow +import * as actions from "constants/action_types"; +import type { Action, Dispatch } from "redux/reducers/media"; +import lbry from "lbry"; + +export const doPlay = () => (dispatch: Dispatch) => + dispatch({ + type: actions.MEDIA_PLAY, + }); + +export const doPause = (id: String, position: String) => ( + dispatch: Dispatch +) => { + if (id && position) { + dispatch({ + type: actions.MEDIA_POSITION, + id, + position, + }); + } + dispatch({ type: actions.MEDIA_PAUSE }); +}; + +export const savePosition = (id: String, position: String) => ( + dispatch: Dispatch +) => + dispatch({ + type: actions.MEDIA_POSITION, + id, + position, + }); diff --git a/src/renderer/redux/reducers/media.js b/src/renderer/redux/reducers/media.js new file mode 100644 index 000000000..242f65be7 --- /dev/null +++ b/src/renderer/redux/reducers/media.js @@ -0,0 +1,39 @@ +// @flow +import * as actions from "constants/action_types"; +import { handleActions } from "util/redux-utils"; + +export type MediaState = { + paused: Boolean, + positions: Object, +}; + +export type Action = any; +export type Dispatch = (action: Action) => any; + +const defaultState = { paused: true, positions: {} }; + +export default handleActions( + { + [actions.MEDIA_PLAY]: (state: MediaState, action: Action) => ({ + ...state, + paused: false, + }), + + [actions.MEDIA_PAUSE]: (state: MediaState, action: Action) => ({ + ...state, + paused: true, + }), + + [actions.MEDIA_POSITION]: (state: MediaState, action: Action) => { + const { id, position } = action; + return { + ...state, + positions: { + ...state.positions, + [id]: position, + }, + }; + }, + }, + defaultState +); diff --git a/src/renderer/redux/selectors/media.js b/src/renderer/redux/selectors/media.js new file mode 100644 index 000000000..070604c2b --- /dev/null +++ b/src/renderer/redux/selectors/media.js @@ -0,0 +1,15 @@ +import * as settings from "constants/settings"; +import { createSelector } from "reselect"; + +const _selectState = state => state.media || {}; + +export const selectMediaPaused = createSelector( + _selectState, + state => state.paused +); + +export const makeSelectMediaPositionForUri = uri => + createSelector(_selectState, state => { + const id = uri.split("#")[1]; + return state.positions[id] || null; + }); diff --git a/src/renderer/store.js b/src/renderer/store.js index f4a61f779..8c6e89277 100644 --- a/src/renderer/store.js +++ b/src/renderer/store.js @@ -14,6 +14,7 @@ import walletReducer from "redux/reducers/wallet"; import shapeShiftReducer from "redux/reducers/shape_shift"; import subscriptionsReducer from "redux/reducers/subscriptions"; import videoReducer from "redux/reducers/video"; +import mediaReducer from "redux/reducers/media"; import { persistStore, autoRehydrate } from "redux-persist"; import createCompressor from "redux-persist-transform-compress"; import createFilter from "redux-persist-transform-filter"; @@ -71,6 +72,7 @@ const reducers = combineReducers({ shapeShift: shapeShiftReducer, subscriptions: subscriptionsReducer, video: videoReducer, + media: mediaReducer, }); const bulkThunk = createBulkThunkMiddleware(); From 7d29c4b91d01c1c5bc8e42ea78466bb40ae314a6 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Thu, 21 Dec 2017 20:22:40 -0500 Subject: [PATCH 02/52] apply starting position directly (no setTimeout) --- src/renderer/component/video/internal/player.jsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/renderer/component/video/internal/player.jsx b/src/renderer/component/video/internal/player.jsx index c0e13acab..7e436f566 100644 --- a/src/renderer/component/video/internal/player.jsx +++ b/src/renderer/component/video/internal/player.jsx @@ -38,11 +38,6 @@ class VideoPlayer extends React.PureComponent { position, } = this.props; - // I'm using a Timeout because I'm not sure where this should happen - if (position > 0) { - setTimeout(() => (mediaElement.currentTime = position), 900); - } - const loadedMetadata = e => { this.setState({ hasMetadata: true, startedPlaying: true }); this.refs.media.children[0].play(); @@ -75,6 +70,7 @@ class VideoPlayer extends React.PureComponent { document.addEventListener("keydown", this.togglePlayListener); const mediaElement = this.refs.media.children[0]; if (mediaElement) { + mediaElement.currentTime = position; mediaElement.addEventListener("play", () => this.props.doPlay()); mediaElement.addEventListener("pause", () => { console.log("CURRENT TIME:", mediaElement.currentTime); From 11a5f9d1d5bc391d7c82f4a60aebc7e0632de24b Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Fri, 22 Dec 2017 18:14:54 -0500 Subject: [PATCH 03/52] use timeupdate instead of pause to update video state --- src/renderer/component/video/index.js | 3 ++- src/renderer/component/video/internal/player.jsx | 8 ++++---- src/renderer/component/video/view.jsx | 2 ++ src/renderer/redux/actions/media.js | 16 ++++------------ 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/renderer/component/video/index.js b/src/renderer/component/video/index.js index bec9e46b6..36c92eab9 100644 --- a/src/renderer/component/video/index.js +++ b/src/renderer/component/video/index.js @@ -45,7 +45,8 @@ const perform = dispatch => ({ changeVolume: volume => dispatch(doChangeVolume(volume)), // setVideoPause: val => dispatch(setVideoPause(val)), doPlay: () => dispatch(doPlay()), - doPause: (id, position) => dispatch(doPause(id, position)), + doPause: () => dispatch(doPause()), + savePosition: (id, position) => dispatch(savePosition(id, position)), }); export default connect(select, perform)(Video); diff --git a/src/renderer/component/video/internal/player.jsx b/src/renderer/component/video/internal/player.jsx index 7e436f566..be2497032 100644 --- a/src/renderer/component/video/internal/player.jsx +++ b/src/renderer/component/video/internal/player.jsx @@ -72,10 +72,10 @@ class VideoPlayer extends React.PureComponent { if (mediaElement) { mediaElement.currentTime = position; mediaElement.addEventListener("play", () => this.props.doPlay()); - mediaElement.addEventListener("pause", () => { - console.log("CURRENT TIME:", mediaElement.currentTime); - this.props.doPause(this.props.mediaId, mediaElement.currentTime); - }); + mediaElement.addEventListener("pause", () => this.props.doPause()); + mediaElement.addEventListener("timeupdate", () => + this.props.savePosition(mediaId, mediaElement.currentTime) + ); mediaElement.addEventListener("click", this.togglePlayListener); mediaElement.addEventListener( "loadedmetadata", diff --git a/src/renderer/component/video/view.jsx b/src/renderer/component/video/view.jsx index 9f793b783..96715c990 100644 --- a/src/renderer/component/video/view.jsx +++ b/src/renderer/component/video/view.jsx @@ -58,6 +58,7 @@ class Video extends React.PureComponent { uri, doPlay, doPause, + savePosition, mediaPaused, mediaPosition, } = this.props; @@ -119,6 +120,7 @@ class Video extends React.PureComponent { volume={volume} doPlay={doPlay} doPause={doPause} + savePosition={savePosition} mediaId={mediaId} paused={mediaPaused} position={mediaPosition} diff --git a/src/renderer/redux/actions/media.js b/src/renderer/redux/actions/media.js index 2ee20e3fa..6cdc6815e 100644 --- a/src/renderer/redux/actions/media.js +++ b/src/renderer/redux/actions/media.js @@ -8,18 +8,10 @@ export const doPlay = () => (dispatch: Dispatch) => type: actions.MEDIA_PLAY, }); -export const doPause = (id: String, position: String) => ( - dispatch: Dispatch -) => { - if (id && position) { - dispatch({ - type: actions.MEDIA_POSITION, - id, - position, - }); - } - dispatch({ type: actions.MEDIA_PAUSE }); -}; +export const doPause = () => (dispatch: Dispatch) => + dispatch({ + type: actions.MEDIA_PAUSE, + }); export const savePosition = (id: String, position: String) => ( dispatch: Dispatch From 61b8e8ee717e19beb9226c5be5ff62ab2dd39196 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Fri, 22 Dec 2017 18:18:00 -0500 Subject: [PATCH 04/52] remove arguments from doPause call in Unmount --- src/renderer/component/video/internal/player.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/renderer/component/video/internal/player.jsx b/src/renderer/component/video/internal/player.jsx index be2497032..3d675c723 100644 --- a/src/renderer/component/video/internal/player.jsx +++ b/src/renderer/component/video/internal/player.jsx @@ -100,9 +100,8 @@ class VideoPlayer extends React.PureComponent { const mediaElement = this.refs.media.children[0]; if (mediaElement) { mediaElement.removeEventListener("click", this.togglePlayListener); - //mediaElement.removeEventListener("play"); ?? } - this.props.doPause(this.props.mediaId, mediaElement.currentTime); + this.props.doPause(); } renderAudio(container, autoplay) { From 59481245864f33fefe3c7f7422cdd450889f019d Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 22 Dec 2017 18:09:06 -0800 Subject: [PATCH 05/52] Added recaptcha compatibility --- src/main/index.js | 418 ++++++++++-------- .../component/userEmailVerify/index.js | 9 +- .../component/userEmailVerify/view.jsx | 7 +- src/renderer/index.js | 28 +- src/renderer/redux/actions/app.js | 13 +- src/renderer/redux/actions/user.js | 41 +- 6 files changed, 313 insertions(+), 203 deletions(-) diff --git a/src/main/index.js b/src/main/index.js index e43a71d7f..0c8e114d6 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1,52 +1,62 @@ // Module imports -const {app, BrowserWindow, ipcMain, Menu, Tray, globalShortcut} = require('electron'); -const path = require('path'); -const url = require('url'); -const jayson = require('jayson'); -const semver = require('semver'); -const https = require('https'); -const keytar = require('keytar'); +const { + app, + BrowserWindow, + ipcMain, + Menu, + Tray, + globalShortcut, +} = require("electron"); +const path = require("path"); +const url = require("url"); +const jayson = require("jayson"); +const semver = require("semver"); +const https = require("https"); +const keytar = require("keytar"); // tree-kill has better cross-platform handling of // killing a process. child-process.kill was unreliable -const kill = require('tree-kill'); -const child_process = require('child_process'); -const assert = require('assert'); +const kill = require("tree-kill"); +const child_process = require("child_process"); +const assert = require("assert"); const localVersion = app.getVersion(); -const setMenu = require('./menu/main-menu.js'); -export const contextMenu = require('./menu/context-menu'); +const setMenu = require("./menu/main-menu.js"); +export const contextMenu = require("./menu/context-menu"); // Debug configs -const isDevelopment = process.env.NODE_ENV === 'development'; +const isDevelopment = process.env.NODE_ENV === "development"; if (isDevelopment) { - try - { - const { default: installExtension, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS } = require('electron-devtools-installer'); - app.on('ready', () => { + try { + const { + default: installExtension, + REACT_DEVELOPER_TOOLS, + REDUX_DEVTOOLS, + } = require("electron-devtools-installer"); + app.on("ready", () => { [REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS].forEach(extension => { installExtension(extension) - .then((name) => console.log(`Added Extension: ${name}`)) - .catch((err) => console.log('An error occurred: ', err)); + .then(name => console.log(`Added Extension: ${name}`)) + .catch(err => console.log("An error occurred: ", err)); }); }); - } - catch (err) - { - console.error(err) + } catch (err) { + console.error(err); } } // Misc constants -const LATEST_RELEASE_API_URL = 'https://api.github.com/repos/lbryio/lbry-app/releases/latest'; -const DAEMON_PATH = process.env.LBRY_DAEMON || path.join(__static, 'daemon/lbrynet-daemon'); +const LATEST_RELEASE_API_URL = + "https://api.github.com/repos/lbryio/lbry-app/releases/latest"; +const DAEMON_PATH = + process.env.LBRY_DAEMON || path.join(__static, "daemon/lbrynet-daemon"); const rendererUrl = isDevelopment ? `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}` : `file://${__dirname}/index.html`; let client = jayson.client.http({ - host: 'localhost', + host: "localhost", port: 5279, - path: '/', - timeout: 1000 + path: "/", + timeout: 1000, }); // Keep a global reference of the window object, if you don't, the window will @@ -84,8 +94,8 @@ function processRequestedUri(uri) { // lbry://channel/#claimid. We remove the slash here as well. // On Linux and Mac, we just return the URI as given. - if (process.platform === 'win32') { - return uri.replace(/\/$/, '').replace('/#', '#'); + if (process.platform === "win32") { + return uri.replace(/\/$/, "").replace("/#", "#"); } else { return uri; } @@ -97,69 +107,87 @@ function processRequestedUri(uri) { * when no windows are open. */ function openItem(fullPath) { - const subprocOptions = { - detached: true, - stdio: 'ignore', - }; + const subprocOptions = { + detached: true, + stdio: "ignore", + }; - let child; - if (process.platform === 'darwin') { - child = child_process.spawn('open', [fullPath], subprocOptions); - } else if (process.platform === 'linux') { - child = child_process.spawn('xdg-open', [fullPath], subprocOptions); - } else if (process.platform === 'win32') { - child = child_process.spawn(fullPath, Object.assign({}, subprocOptions, {shell: true})); - } + let child; + if (process.platform === "darwin") { + child = child_process.spawn("open", [fullPath], subprocOptions); + } else if (process.platform === "linux") { + child = child_process.spawn("xdg-open", [fullPath], subprocOptions); + } else if (process.platform === "win32") { + child = child_process.spawn( + fullPath, + Object.assign({}, subprocOptions, { shell: true }) + ); + } - // Causes child process reference to be garbage collected, allowing main process to exit - child.unref(); + // Causes child process reference to be garbage collected, allowing main process to exit + child.unref(); } function getPidsForProcessName(name) { - if (process.platform === 'win32') { - const tasklistOut = child_process.execSync(`tasklist /fi "Imagename eq ${name}.exe" /nh`, {encoding: 'utf8'}); - if (tasklistOut.startsWith('INFO')) { + if (process.platform === "win32") { + const tasklistOut = child_process.execSync( + `tasklist /fi "Imagename eq ${name}.exe" /nh`, + { encoding: "utf8" } + ); + if (tasklistOut.startsWith("INFO")) { return []; } else { - return tasklistOut.match(/[^\r\n]+/g).map((line) => line.split(/\s+/)[1]); // Second column of every non-empty line + return tasklistOut.match(/[^\r\n]+/g).map(line => line.split(/\s+/)[1]); // Second column of every non-empty line } } else { - const pgrepOut = child_process.spawnSync('pgrep', ['-x', name], {encoding: 'utf8'}).stdout; + const pgrepOut = child_process.spawnSync("pgrep", ["-x", name], { + encoding: "utf8", + }).stdout; return pgrepOut.match(/\d+/g); } } -function createWindow () { +function createWindow() { // Disable renderer process's webSecurity on development to enable CORS. win = isDevelopment - ? new BrowserWindow({backgroundColor: '#155B4A', minWidth: 800, minHeight: 600, webPreferences: {webSecurity: false}}) - : new BrowserWindow({backgroundColor: '#155B4A', minWidth: 800, minHeight: 600}); + ? new BrowserWindow({ + backgroundColor: "#155B4A", + minWidth: 800, + minHeight: 600, + webPreferences: { webSecurity: false }, + }) + : new BrowserWindow({ + backgroundColor: "#155B4A", + minWidth: 800, + minHeight: 600, + }); win.webContents.session.setUserAgent(`LBRY/${localVersion}`); - win.maximize() + win.maximize(); if (isDevelopment) { win.webContents.openDevTools(); } - win.loadURL(rendererUrl) - if (openUri) { // We stored and received a URI that an external app requested before we had a window object - win.webContents.on('did-finish-load', () => { - win.webContents.send('open-uri-requested', openUri); + win.loadURL(rendererUrl); + if (openUri) { + // We stored and received a URI that an external app requested before we had a window object + win.webContents.on("did-finish-load", () => { + win.webContents.send("open-uri-requested", openUri, true); }); } win.removeAllListeners(); - win.on('close', function(event) { + win.on("close", function(event) { if (minimize) { event.preventDefault(); win.hide(); } - }) + }); - win.on('closed', () => { - win = null - }) + win.on("closed", () => { + win = null; + }); win.on("hide", () => { // Checks what to show in the tray icon menu @@ -176,7 +204,7 @@ function createWindow () { if (minimize) updateTray(); // Unregisters Alt+F4 shortcut - globalShortcut.unregister('Alt+F4'); + globalShortcut.unregister("Alt+F4"); }); win.on("focus", () => { @@ -184,23 +212,22 @@ function createWindow () { if (minimize) updateTray(); // Registers shortcut for closing(quitting) the app - globalShortcut.register('Alt+F4', () => safeQuit()); + globalShortcut.register("Alt+F4", () => safeQuit()); - win.webContents.send('window-is-focused', null); + win.webContents.send("window-is-focused", null); }); // Menu bar win.setAutoHideMenuBar(true); win.setMenuBarVisibility(isDevelopment); setMenu(); +} -}; - -function createTray () { +function createTray() { // Minimize to tray logic follows: // Set the tray icon let iconPath; - if (process.platform === 'darwin') { + if (process.platform === "darwin") { // Using @2x for mac retina screens so the icon isn't blurry // file name needs to include "Template" at the end for dark menu bar iconPath = path.join(__static, "/img/fav/macTemplate@2x.png"); @@ -211,9 +238,9 @@ function createTray () { tray = new Tray(iconPath); tray.setToolTip("LBRY App"); tray.setTitle("LBRY"); - tray.on('double-click', () => { - win.show() - }) + tray.on("double-click", () => { + win.show(); + }); } // This needs to be done as for linux the context menu doesn't update automatically(docs) @@ -226,27 +253,26 @@ function updateTray() { } } -function getMenuTemplate () { +function getMenuTemplate() { return [ getToggleItem(), { label: "Quit", click: () => safeQuit(), }, - ] + ]; - function getToggleItem () { + function getToggleItem() { if (win.isVisible() && win.isFocused()) { return { - label: 'Hide LBRY App', - click: () => win.hide() - - } + label: "Hide LBRY App", + click: () => win.hide(), + }; } else { return { - label: 'Show LBRY App', - click: () => win.show() - } + label: "Show LBRY App", + click: () => win.show(), + }; } } } @@ -256,20 +282,19 @@ function handleOpenUriRequested(uri) { // Window not created yet, so store up requested URI for when it is openUri = processRequestedUri(uri); } else { - if (win.isMinimized()) { - win.restore() + win.restore(); } else if (!win.isVisible()) { - win.show() + win.show(); } win.focus(); - win.webContents.send('open-uri-requested', processRequestedUri(uri)); + win.webContents.send("open-uri-requested", processRequestedUri(uri)); } } function handleDaemonSubprocessExited() { - console.log('The daemon has exited.'); + console.log("The daemon has exited."); daemonSubprocess = null; if (!daemonStopRequested) { // We didn't request to stop the daemon, so display a @@ -277,27 +302,31 @@ function handleDaemonSubprocessExited() { // // TODO: maybe it would be better to restart the daemon? if (win) { - console.log('Did not request daemon stop, so quitting in 5 seconds.'); + console.log("Did not request daemon stop, so quitting in 5 seconds."); win.loadURL(`file://${__static}/warning.html`); setTimeout(quitNow, 5000); } else { - console.log('Did not request daemon stop, so quitting.'); + console.log("Did not request daemon stop, so quitting."); quitNow(); } } } function launchDaemon() { - assert(!daemonSubprocess, 'Tried to launch daemon twice'); + assert(!daemonSubprocess, "Tried to launch daemon twice"); - console.log('Launching daemon:', DAEMON_PATH) - daemonSubprocess = child_process.spawn(DAEMON_PATH) + console.log("Launching daemon:", DAEMON_PATH); + daemonSubprocess = child_process.spawn(DAEMON_PATH); // Need to handle the data event instead of attaching to // process.stdout because the latter doesn't work. I believe on // windows it buffers stdout and we don't get any meaningful output - daemonSubprocess.stdout.on('data', (buf) => {console.log(String(buf).trim());}); - daemonSubprocess.stderr.on('data', (buf) => {console.log(String(buf).trim());}); - daemonSubprocess.on('exit', handleDaemonSubprocessExited); + daemonSubprocess.stdout.on("data", buf => { + console.log(String(buf).trim()); + }); + daemonSubprocess.stderr.on("data", buf => { + console.log(String(buf).trim()); + }); + daemonSubprocess.on("exit", handleDaemonSubprocessExited); } /* @@ -318,7 +347,7 @@ function quitNow() { safeQuit(); } -const isSecondaryInstance = app.makeSingleInstance((argv) => { +const isSecondaryInstance = app.makeSingleInstance(argv => { if (argv.length >= 2) { handleOpenUriRequested(argv[1]); // This will handle restoring and focusing the window } else if (win) { @@ -331,25 +360,23 @@ const isSecondaryInstance = app.makeSingleInstance((argv) => { } }); -if (isSecondaryInstance) { // We're not in the original process, so quit +if (isSecondaryInstance) { + // We're not in the original process, so quit quitNow(); } function launchDaemonIfNotRunning() { // Check if the daemon is already running. If we get // an error its because its not running - console.log('Checking for lbrynet daemon'); - client.request( - 'status', [], - function (err, res) { - if (err) { - console.log('lbrynet daemon needs to be launched') - launchDaemon(); - } else { - console.log('lbrynet daemon is already running') - } + console.log("Checking for lbrynet daemon"); + client.request("status", [], function(err, res) { + if (err) { + console.log("lbrynet daemon needs to be launched"); + launchDaemon(); + } else { + console.log("lbrynet daemon is already running"); } - ); + }); } /* @@ -358,21 +385,31 @@ function launchDaemonIfNotRunning() { * tries to force kill them. */ function forceKillAllDaemonsAndQuit() { - console.log('Attempting to force kill any running lbrynet-daemon instances...'); + console.log( + "Attempting to force kill any running lbrynet-daemon instances..." + ); - const daemonPids = getPidsForProcessName('lbrynet-daemon'); + const daemonPids = getPidsForProcessName("lbrynet-daemon"); if (!daemonPids) { - console.log('No lbrynet-daemon found running.'); + console.log("No lbrynet-daemon found running."); quitNow(); } else { - console.log(`Found ${daemonPids.length} running daemon instances. Attempting to force kill...`); + console.log( + `Found ${ + daemonPids.length + } running daemon instances. Attempting to force kill...` + ); for (const pid of daemonPids) { let daemonKillAttemptsComplete = 0; - kill(pid, 'SIGKILL', (err) => { + kill(pid, "SIGKILL", err => { daemonKillAttemptsComplete++; if (err) { - console.log(`Failed to force kill daemon task with pid ${pid}. Error message: ${err.message}`); + console.log( + `Failed to force kill daemon task with pid ${pid}. Error message: ${ + err.message + }` + ); } else { console.log(`Force killed daemon task with pid ${pid}.`); } @@ -384,15 +421,15 @@ function forceKillAllDaemonsAndQuit() { } } -app.setAsDefaultProtocolClient('lbry'); +app.setAsDefaultProtocolClient("lbry"); -app.on('ready', function() { +app.on("ready", function() { launchDaemonIfNotRunning(); if (process.platform === "linux") { - checkLinuxTraySupport( err => { + checkLinuxTraySupport(err => { if (!err) createTray(); else minimize = false; - }) + }); } else { createTray(); } @@ -400,36 +437,35 @@ app.on('ready', function() { }); // Quit when all windows are closed. -app.on('window-all-closed', () => { +app.on("window-all-closed", () => { // On macOS it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q - if (process.platform !== 'darwin') { - app.quit() + if (process.platform !== "darwin") { + app.quit(); } -}) +}); - -app.on('before-quit', (event) => { +app.on("before-quit", event => { if (!readyToQuit) { // We need to shutdown the daemon before we're ready to actually quit. This // event will be triggered re-entrantly once preparation is done. event.preventDefault(); shutdownDaemonAndQuit(); } else { - console.log('Quitting.') + console.log("Quitting."); } }); -app.on('activate', () => { +app.on("activate", () => { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (win === null) { - createWindow() + createWindow(); } }); -if (process.platform === 'darwin') { - app.on('open-url', (event, uri) => { +if (process.platform === "darwin") { + app.on("open-url", (event, uri) => { handleOpenUriRequested(uri); }); } else if (process.argv.length >= 2) { @@ -440,14 +476,18 @@ if (process.platform === 'darwin') { // then calls quitNow() to quit for real. function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) { function doShutdown() { - console.log('Shutting down daemon'); + console.log("Shutting down daemon"); daemonStopRequested = true; - client.request('daemon_stop', [], (err, res) => { + client.request("daemon_stop", [], (err, res) => { if (err) { - console.log(`received error when stopping lbrynet-daemon. Error message: ${err.message}\n`); - console.log('You will need to manually kill the daemon.'); + console.log( + `received error when stopping lbrynet-daemon. Error message: ${ + err.message + }\n` + ); + console.log("You will need to manually kill the daemon."); } else { - console.log('Successfully stopped daemon via RPC call.') + console.log("Successfully stopped daemon via RPC call."); quitNow(); } }); @@ -456,7 +496,7 @@ function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) { if (daemonSubprocess) { doShutdown(); } else if (!evenIfNotStartedByApp) { - console.log('Not killing lbrynet-daemon because app did not start it'); + console.log("Not killing lbrynet-daemon because app did not start it"); quitNow(); } else { doShutdown(); @@ -467,24 +507,27 @@ function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) { } // Taken from webtorrent-desktop -function checkLinuxTraySupport (cb) { +function checkLinuxTraySupport(cb) { // Check that we're on Ubuntu (or another debian system) and that we have // libappindicator1. - child_process.exec('dpkg --get-selections libappindicator1', function (err, stdout) { - if (err) return cb(err) + child_process.exec("dpkg --get-selections libappindicator1", function( + err, + stdout + ) { + if (err) return cb(err); // Unfortunately there's no cleaner way, as far as I can tell, to check // whether a debian package is installed: - if (stdout.endsWith('\tinstall\n')) { - cb(null) + if (stdout.endsWith("\tinstall\n")) { + cb(null); } else { - cb(new Error('debian package not installed')) + cb(new Error("debian package not installed")); } - }) + }); } -ipcMain.on('upgrade', (event, installerPath) => { - app.on('quit', () => { - console.log('Launching upgrade installer at', installerPath); +ipcMain.on("upgrade", (event, installerPath) => { + app.on("quit", () => { + console.log("Launching upgrade installer at", installerPath); // This gets triggered called after *all* other quit-related events, so // we'll only get here if we're fully prepared and quitting for real. openItem(installerPath); @@ -497,58 +540,77 @@ ipcMain.on('upgrade', (event, installerPath) => { shutdownDaemonAndQuit(true); // wait for daemon to shut down before upgrading // what to do if no shutdown in a long time? - console.log('Update downloaded to', installerPath); - console.log('The app will close, and you will be prompted to install the latest version of LBRY.'); - console.log('After the install is complete, please reopen the app.'); + console.log("Update downloaded to", installerPath); + console.log( + "The app will close, and you will be prompted to install the latest version of LBRY." + ); + console.log("After the install is complete, please reopen the app."); }); -ipcMain.on('version-info-requested', () => { +ipcMain.on("version-info-requested", () => { function formatRc(ver) { // Adds dash if needed to make RC suffix semver friendly - return ver.replace(/([^-])rc/, '$1-rc'); + return ver.replace(/([^-])rc/, "$1-rc"); } - let result = ''; + let result = ""; const opts = { headers: { - 'User-Agent': `LBRY/${localVersion}`, - } + "User-Agent": `LBRY/${localVersion}`, + }, }; - const req = https.get(Object.assign(opts, url.parse(LATEST_RELEASE_API_URL)), (res) => { - res.on('data', (data) => { - result += data; - }); - res.on('end', () => { - const tagName = JSON.parse(result).tag_name; - const [_, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/); - if (!remoteVersion) { - if (win) { - win.webContents.send('version-info-received', null); + const req = https.get( + Object.assign(opts, url.parse(LATEST_RELEASE_API_URL)), + res => { + res.on("data", data => { + result += data; + }); + res.on("end", () => { + const tagName = JSON.parse(result).tag_name; + const [_, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/); + if (!remoteVersion) { + if (win) { + win.webContents.send("version-info-received", null); + } + } else { + const upgradeAvailable = semver.gt( + formatRc(remoteVersion), + formatRc(localVersion) + ); + if (win) { + win.webContents.send("version-info-received", { + remoteVersion, + localVersion, + upgradeAvailable, + }); + } } - } else { - const upgradeAvailable = semver.gt(formatRc(remoteVersion), formatRc(localVersion)); - if (win) { - win.webContents.send('version-info-received', {remoteVersion, localVersion, upgradeAvailable}); - } - } - }) - }); + }); + } + ); - req.on('error', (err) => { - console.log('Failed to get current version from GitHub. Error:', err); + req.on("error", err => { + console.log("Failed to get current version from GitHub. Error:", err); if (win) { - win.webContents.send('version-info-received', null); + win.webContents.send("version-info-received", null); } }); }); -ipcMain.on('get-auth-token', (event) => { +ipcMain.on("get-auth-token", event => { keytar.getPassword("LBRY", "auth_token").then(token => { - event.sender.send('auth-token-response', token ? token.toString().trim() : null) + event.sender.send( + "auth-token-response", + token ? token.toString().trim() : null + ); }); }); -ipcMain.on('set-auth-token', (event, token) => { - keytar.setPassword("LBRY", "auth_token", token ? token.toString().trim() : null); +ipcMain.on("set-auth-token", (event, token) => { + keytar.setPassword( + "LBRY", + "auth_token", + token ? token.toString().trim() : null + ); }); diff --git a/src/renderer/component/userEmailVerify/index.js b/src/renderer/component/userEmailVerify/index.js index e0fa0902b..872471e23 100644 --- a/src/renderer/component/userEmailVerify/index.js +++ b/src/renderer/component/userEmailVerify/index.js @@ -1,6 +1,9 @@ import React from "react"; import { connect } from "react-redux"; -import { doUserEmailVerify } from "redux/actions/user"; +import { + doUserEmailVerify, + doUserEmailVerifyFailure, +} from "redux/actions/user"; import { selectEmailVerifyIsPending, selectEmailToVerify, @@ -20,7 +23,9 @@ const select = state => ({ }); const perform = dispatch => ({ - verifyUserEmail: code => dispatch(doUserEmailVerify(code)), + verifyUserEmail: (code, recaptcha) => + dispatch(doUserEmailVerify(code, recaptcha)), + verifyUserEmailFailure: error => dispatch(doUserEmailVerifyFailure(error)), }); export default connect(select, perform)(UserEmailVerify); diff --git a/src/renderer/component/userEmailVerify/view.jsx b/src/renderer/component/userEmailVerify/view.jsx index 2e330acbe..146045904 100644 --- a/src/renderer/component/userEmailVerify/view.jsx +++ b/src/renderer/component/userEmailVerify/view.jsx @@ -20,7 +20,12 @@ class UserEmailVerify extends React.PureComponent { handleSubmit() { const { code } = this.state; - this.props.verifyUserEmail(code); + try { + let verification = JSON.parse(atob(code)); + this.props.verifyUserEmail(verification.token, verification.recaptcha); + } catch (error) { + this.props.verifyUserEmailFailure("Invalid Verification Token"); + } } render() { diff --git a/src/renderer/index.js b/src/renderer/index.js index e3ed7836b..a79cc9a81 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -5,8 +5,13 @@ import SnackBar from "component/snackBar"; import { Provider } from "react-redux"; import store from "store.js"; import SplashScreen from "component/splash"; -import { doDaemonReady } from "redux/actions/app"; +import { + doDaemonReady, + doShowSnackBar, + doConditionalAuthNavigate, +} from "redux/actions/app"; import { doNavigate } from "redux/actions/navigation"; +import { doUserEmailVerify } from "redux/actions/user"; import { doDownloadLanguages } from "redux/actions/settings"; import * as types from "constants/action_types"; import amplitude from "amplitude-js"; @@ -37,9 +42,26 @@ window.addEventListener("contextmenu", event => { event.preventDefault(); }); -ipcRenderer.on("open-uri-requested", (event, uri) => { +ipcRenderer.on("open-uri-requested", (event, uri, newSession) => { if (uri && uri.startsWith("lbry://")) { - app.store.dispatch(doNavigate("/show", { uri })); + if (uri.startsWith("lbry://?verify=")) { + let verification = {}; + try { + verification = JSON.parse(atob(uri.substring(15))); + } catch (error) {} + if (verification.token && verification.recaptcha) { + app.store.dispatch(doConditionalAuthNavigate(newSession)); + app.store.dispatch( + doUserEmailVerify(verification.token, verification.recaptcha) + ); + } else { + app.store.dispatch( + doShowSnackBar({ message: "Invalid Verification URI" }) + ); + } + } else { + app.store.dispatch(doNavigate("/show", { uri })); + } } }); diff --git a/src/renderer/redux/actions/app.js b/src/renderer/redux/actions/app.js index bf82fb269..7bcb43473 100644 --- a/src/renderer/redux/actions/app.js +++ b/src/renderer/redux/actions/app.js @@ -7,6 +7,7 @@ import { selectUpgradeFilename, selectIsUpgradeSkipped, selectRemoteVersion, + selectCurrentModal, } from "redux/selectors/app"; import { doFetchDaemonSettings } from "redux/actions/settings"; import { doBalanceSubscribe } from "redux/actions/wallet"; @@ -14,8 +15,7 @@ import { doAuthenticate } from "redux/actions/user"; import { doFetchFileInfosAndPublishedClaims } from "redux/actions/file_info"; import * as modals from "constants/modal_types"; import { doFetchRewardedContent } from "redux/actions/content"; -import { selectCurrentModal } from "redux/selectors/app"; - +import { doAuthNavigate } from "redux/actions/navigation"; const { remote, ipcRenderer, shell } = require("electron"); const path = require("path"); const { download } = remote.require("electron-dl"); @@ -266,3 +266,12 @@ export function doChangeVolume(volume) { }); }; } + +export function doConditionalAuthNavigate(newSession) { + return function(dispatch, getState) { + const state = getState(); + if (newSession || selectCurrentModal(state) !== "email_collection") { + dispatch(doAuthNavigate()); + } + }; +} diff --git a/src/renderer/redux/actions/user.js b/src/renderer/redux/actions/user.js index 7111369e8..3796db0d1 100644 --- a/src/renderer/redux/actions/user.js +++ b/src/renderer/redux/actions/user.js @@ -68,14 +68,14 @@ export function doUserEmailNew(email) { data: { email }, }); dispatch(doUserFetch()); - } + }; const failure = error => { dispatch({ type: types.USER_EMAIL_NEW_FAILURE, data: { error }, }); - } + }; lbryio .call( @@ -86,12 +86,14 @@ export function doUserEmailNew(email) { ) .catch(error => { if (error.response && error.response.status == 409) { - return lbryio.call( - "user_email", - "resend_token", - { email: email, only_if_expired: true }, - "post" - ).then(success, failure); + return lbryio + .call( + "user_email", + "resend_token", + { email: email, only_if_expired: true }, + "post" + ) + .then(success, failure); } throw error; }) @@ -99,21 +101,25 @@ export function doUserEmailNew(email) { }; } -export function doUserEmailVerify(verificationToken) { +export function doUserEmailVerify(verificationToken, recaptcha) { return function(dispatch, getState) { const email = selectEmailToVerify(getState()); - verificationToken = verificationToken.toString().trim(); dispatch({ type: types.USER_EMAIL_VERIFY_STARTED, code: verificationToken, + recaptcha: recaptcha, }); lbryio .call( "user_email", "confirm", - { verification_token: verificationToken, email: email }, + { + verification_token: verificationToken, + email: email, + recaptcha: recaptcha, + }, "post" ) .then(userEmail => { @@ -128,12 +134,13 @@ export function doUserEmailVerify(verificationToken) { throw new Error("Your email is still not verified."); //shouldn't happen } }) - .catch(error => { - dispatch({ - type: types.USER_EMAIL_VERIFY_FAILURE, - data: { error }, - }); - }); + .catch(error => dispatch(doUserEmailVerifyFailure(error))); + }; +} +export function doUserEmailVerifyFailure(error) { + return { + type: types.USER_EMAIL_VERIFY_FAILURE, + data: { error }, }; } From 3d95251865fa9c529ab0a8e7f99a4fdae2d17ebc Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 22 Dec 2017 19:15:52 -0800 Subject: [PATCH 06/52] Update CHANGELOG.md --- CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a57edac4..06aab92fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,14 +9,17 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added * Added copy address button to the Wallet Address component on Send / Receive (#875) + * Link to creators’ channels on homepage (#869) + * Pause playing video when file is opened (#880) + * Reenabled rewards with new verification process (#897) * ### Changed - * + * Contributor documentation * ### Fixed - * + * Linux app categorization (#877) * ### Deprecated From 101650f37214930188f4addc6971edcd11689771 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 22 Dec 2017 19:16:15 -0800 Subject: [PATCH 07/52] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06aab92fb..c3a9152ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * ### Changed - * Contributor documentation + * Contributor documentation (#879) * ### Fixed From 1cf8826ac0eec22ab6051c6d554cf526531b415e Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 22 Dec 2017 19:18:42 -0800 Subject: [PATCH 08/52] =?UTF-8?q?Bump=20version:=200.19.1=20=E2=86=92=200.?= =?UTF-8?q?19.2rc1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 91764cc37..49dd1aad8 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.1 +current_version = 0.19.2rc1 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/package.json b/package.json index ff83432b9..42b8b3324 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.1", + "version": "0.19.2rc1", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": { From 6c22d73a0c89e902350f608902c4cfbf2d6a87ff Mon Sep 17 00:00:00 2001 From: Thomas Zarebczan Date: Fri, 22 Dec 2017 23:37:59 -0500 Subject: [PATCH 09/52] fix snackbar text --- src/renderer/rewards.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/rewards.js b/src/renderer/rewards.js index 0fe0121e0..aeafbc590 100644 --- a/src/renderer/rewards.js +++ b/src/renderer/rewards.js @@ -41,7 +41,7 @@ const rewards = {}; rewards.TYPE_NEW_DEVELOPER = "new_developer"; rewards.TYPE_NEW_USER = "new_user"; -rewards.TYPE_CONFIRM_EMAIL = "verified_email"; +rewards.TYPE_CONFIRM_EMAIL = "confirm_email"; rewards.TYPE_FIRST_CHANNEL = "new_channel"; rewards.TYPE_FIRST_STREAM = "first_stream"; rewards.TYPE_MANY_DOWNLOADS = "many_downloads"; From b3e47a8f8615e664c1fa7682a9c79a398d8cbc9d Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 22 Dec 2017 22:25:05 -0800 Subject: [PATCH 10/52] =?UTF-8?q?Bump=20version:=200.19.2rc1=20=E2=86=92?= =?UTF-8?q?=200.19.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CHANGELOG.md | 27 +++++++++++++++++++++------ package.json | 2 +- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 49dd1aad8..dd3d60359 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.2rc1 +current_version = 0.19.2 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/CHANGELOG.md b/CHANGELOG.md index c3a9152ab..7e2feea50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,18 +8,15 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added - * Added copy address button to the Wallet Address component on Send / Receive (#875) - * Link to creators’ channels on homepage (#869) - * Pause playing video when file is opened (#880) - * Reenabled rewards with new verification process (#897) + * * ### Changed - * Contributor documentation (#879) + * * ### Fixed - * Linux app categorization (#877) + * * ### Deprecated @@ -30,6 +27,24 @@ Web UI version numbers should always match the corresponding version of LBRY App * * +## [0.19.2] - 2017-12-22 + +### Added + * Added copy address button to the Wallet Address component on Send / Receive (#875) + * Link to creators’ channels on homepage (#869) + * Pause playing video when file is opened (#880) + * Reenabled rewards with new verification process (#897) + + +### Changed + * Contributor documentation (#879) + + +### Fixed + * Linux app categorization (#877) + + + ## [0.19.1] - 2017-12-13 ### Added diff --git a/package.json b/package.json index 42b8b3324..f15fb3714 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.2rc1", + "version": "0.19.2", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": { From d038a6544bda899a63dec336ccff2743aa757912 Mon Sep 17 00:00:00 2001 From: Thomas Zarebczan Date: Sat, 23 Dec 2017 01:29:49 -0500 Subject: [PATCH 11/52] update message about rewards --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e2feea50..e0da8b5c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * Added copy address button to the Wallet Address component on Send / Receive (#875) * Link to creators’ channels on homepage (#869) * Pause playing video when file is opened (#880) - * Reenabled rewards with new verification process (#897) + * Add captcha to verification process (#897) ### Changed From f3c92acacf350a1f9f34ee50ee8340c271afb868 Mon Sep 17 00:00:00 2001 From: Igor Gassmann Date: Tue, 26 Dec 2017 17:13:05 -0300 Subject: [PATCH 12/52] Fix fetching daemon settings bug --- src/renderer/redux/actions/settings.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/renderer/redux/actions/settings.js b/src/renderer/redux/actions/settings.js index ec6506b15..54af9e300 100644 --- a/src/renderer/redux/actions/settings.js +++ b/src/renderer/redux/actions/settings.js @@ -1,10 +1,10 @@ import * as ACTIONS from 'constants/action_types'; import * as SETTINGS from 'constants/settings'; - -import Lbry from 'lbry'; import Fs from 'fs'; import Http from 'http'; +import Lbry from 'lbry'; + export function doFetchDaemonSettings() { return function(dispatch) { Lbry.settings_get().then(settings => { @@ -20,14 +20,14 @@ export function doFetchDaemonSettings() { export function doSetDaemonSetting(key, value) { return function(dispatch) { - const settings = {}; - settings[key] = value; - Lbry.settings_set(settings).then(settings); - Lbry.settings_get().then(remoteSettings => { + const newSettings = {}; + newSettings[key] = value; + Lbry.settings_set(newSettings).then(newSettings); + Lbry.settings_get().then(settings => { dispatch({ type: ACTIONS.DAEMON_SETTINGS_RECEIVED, data: { - remoteSettings, + settings, }, }); }); From 1984d654e647453bd92e6afa1700540a4785e798 Mon Sep 17 00:00:00 2001 From: Thomas Zarebczan Date: Wed, 27 Dec 2017 13:52:41 -0500 Subject: [PATCH 13/52] fix verified email snackbar, take 2 the API call uses verified_email, reverting and fixing the message type. --- src/renderer/rewards.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderer/rewards.js b/src/renderer/rewards.js index aeafbc590..a56533c72 100644 --- a/src/renderer/rewards.js +++ b/src/renderer/rewards.js @@ -9,7 +9,7 @@ function rewardMessage(type, amount) { amount ), new_user: __("You earned %s LBC new user reward.", amount), - confirm_email: __( + verified_email: __( "You earned %s LBC for verifying your email address.", amount ), @@ -41,7 +41,7 @@ const rewards = {}; rewards.TYPE_NEW_DEVELOPER = "new_developer"; rewards.TYPE_NEW_USER = "new_user"; -rewards.TYPE_CONFIRM_EMAIL = "confirm_email"; +rewards.TYPE_CONFIRM_EMAIL = "verified_email"; rewards.TYPE_FIRST_CHANNEL = "new_channel"; rewards.TYPE_FIRST_STREAM = "first_stream"; rewards.TYPE_MANY_DOWNLOADS = "many_downloads"; From 0a940829830cf21e2db27dd3acbae3d307ba95f3 Mon Sep 17 00:00:00 2001 From: Igor Gassmann Date: Wed, 27 Dec 2017 20:48:11 -0300 Subject: [PATCH 14/52] Convert anonymous functions to arrow functions --- src/renderer/index.js | 26 ++--- src/renderer/jsonrpc.js | 4 +- src/renderer/lbry.js | 39 +++---- src/renderer/lbryio.js | 10 +- src/renderer/lbryuri.js | 12 +-- src/renderer/redux/actions/app.js | 53 +++++----- src/renderer/redux/actions/availability.js | 2 +- src/renderer/redux/actions/content.js | 57 ++++++----- src/renderer/redux/actions/cost_info.js | 2 +- src/renderer/redux/actions/file_info.js | 30 +++--- src/renderer/redux/actions/navigation.js | 16 ++- src/renderer/redux/actions/rewards.js | 10 +- src/renderer/redux/actions/search.js | 2 +- src/renderer/redux/actions/settings.js | 12 +-- src/renderer/redux/actions/user.js | 18 ++-- src/renderer/redux/actions/wallet.js | 28 +++--- src/renderer/redux/reducers/app.js | 80 ++++++--------- src/renderer/redux/reducers/availability.js | 4 +- src/renderer/redux/reducers/claims.js | 26 +++-- src/renderer/redux/reducers/content.js | 15 ++- src/renderer/redux/reducers/cost_info.js | 4 +- src/renderer/redux/reducers/file_info.js | 25 +++-- src/renderer/redux/reducers/navigation.js | 7 +- src/renderer/redux/reducers/rewards.js | 15 ++- src/renderer/redux/reducers/search.js | 12 +-- src/renderer/redux/reducers/settings.js | 13 ++- src/renderer/redux/reducers/user.js | 106 ++++++++------------ src/renderer/redux/reducers/wallet.js | 57 +++++------ src/renderer/redux/selectors/app.js | 2 - src/renderer/redux/selectors/claims.js | 13 +-- src/renderer/redux/selectors/content.js | 2 +- src/renderer/redux/selectors/file_info.js | 41 +------- src/renderer/redux/selectors/search.js | 6 +- src/renderer/redux/selectors/settings.js | 5 - src/renderer/rewards.js | 2 +- src/renderer/util/setBadge.js | 2 +- src/renderer/util/shape_shift.js | 4 +- src/renderer/util/throttle.js | 6 +- 38 files changed, 328 insertions(+), 440 deletions(-) diff --git a/src/renderer/index.js b/src/renderer/index.js index a5ef55409..19350e8ce 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -1,20 +1,20 @@ +import amplitude from 'amplitude-js'; +import App from 'component/app'; +import SnackBar from 'component/snackBar'; +import SplashScreen from 'component/splash'; +import * as ACTIONS from 'constants/action_types'; +import { ipcRenderer, remote, shell } from 'electron'; +import lbry from 'lbry'; /* eslint-disable react/jsx-filename-extension */ import React from 'react'; import ReactDOM from 'react-dom'; -import App from 'component/app'; -import SnackBar from 'component/snackBar'; import { Provider } from 'react-redux'; -import store from 'store'; -import SplashScreen from 'component/splash'; -import { doDaemonReady, doShowSnackBar, doConditionalAuthNavigate } from 'redux/actions/app'; -import { doUserEmailVerify } from 'redux/actions/user'; +import { doConditionalAuthNavigate, doDaemonReady, doShowSnackBar } from 'redux/actions/app'; import { doNavigate } from 'redux/actions/navigation'; import { doDownloadLanguages } from 'redux/actions/settings'; -import * as ACTIONS from 'constants/action_types'; -import amplitude from 'amplitude-js'; -import lbry from 'lbry'; +import { doUserEmailVerify } from 'redux/actions/user'; import 'scss/all.scss'; -import { ipcRenderer, remote, shell } from 'electron'; +import store from 'store'; import app from './app'; const { contextMenu } = remote.require('./main.js'); @@ -64,10 +64,10 @@ ipcRenderer.on('window-is-focused', () => { dock.setBadge(''); }); -(function(history, ...args) { +((history, ...args) => { const { replaceState } = history; const newHistory = history; - newHistory.replaceState = function(_, __, path) { + newHistory.replaceState = (_, __, path) => { amplitude.getInstance().logEvent('NAVIGATION', { destination: path ? path.slice(1) : path }); return replaceState.apply(history, args); }; @@ -101,7 +101,7 @@ document.addEventListener('click', event => { } }); -const init = function initializeReactApp() { +const init = () => { app.store.dispatch(doDownloadLanguages()); function onDaemonReady() { diff --git a/src/renderer/jsonrpc.js b/src/renderer/jsonrpc.js index a94ba4fe8..8e11c4f12 100644 --- a/src/renderer/jsonrpc.js +++ b/src/renderer/jsonrpc.js @@ -1,13 +1,13 @@ const jsonrpc = {}; -jsonrpc.call = function callJsonRpc( +jsonrpc.call = ( connectionString, method, params, callback, errorCallback, connectFailedCallback -) { +) => { function checkAndParse(response) { if (response.status >= 200 && response.status < 300) { return response.json(); diff --git a/src/renderer/lbry.js b/src/renderer/lbry.js index 27cd3ec14..0123f08c2 100644 --- a/src/renderer/lbry.js +++ b/src/renderer/lbry.js @@ -1,5 +1,5 @@ -import jsonrpc from 'jsonrpc'; import { ipcRenderer } from 'electron'; +import jsonrpc from 'jsonrpc'; const CHECK_DAEMON_STARTED_TRY_NUMBER = 200; @@ -19,11 +19,10 @@ const lbryProxy = new Proxy(Lbry, { return target[name]; } - return function(params = {}) { - return new Promise((resolve, reject) => { + return params => + new Promise((resolve, reject) => { apiCall(name, params, resolve, reject); }); - }; }, }); @@ -76,7 +75,7 @@ function removePendingPublishIfNeeded({ name, channelName, outpoint }) { * Gets the current list of pending publish attempts. Filters out any that have timed out and * removes them from the list. */ -Lbry.getPendingPublishes = function() { +Lbry.getPendingPublishes = () => { const pendingPublishes = getLocal('pendingPublishes') || []; const newPendingPublishes = pendingPublishes.filter( pub => Date.now() - pub.time <= Lbry.pendingPublishTimeout @@ -110,7 +109,7 @@ function pendingPublishToDummyFileInfo({ name, outpoint, claimId }) { // core Lbry.connectPromise = null; -Lbry.connect = function() { +Lbry.connect = () => { if (Lbry.connectPromise === null) { Lbry.connectPromise = new Promise((resolve, reject) => { let tryNum = 0; @@ -144,7 +143,7 @@ Lbry.connect = function() { * This currently includes a work-around to cache the file in local storage so that the pending * publish can appear in the UI immediately. */ -Lbry.publishDeprecated = function(params, fileListedCallback, publishedCallback, errorCallback) { +Lbry.publishDeprecated = (params, fileListedCallback, publishedCallback, errorCallback) => { // Give a short grace period in case publish() returns right away or (more likely) gives an error const returnPendingTimeout = setTimeout( () => { @@ -173,11 +172,9 @@ Lbry.publishDeprecated = function(params, fileListedCallback, publishedCallback, ); }; -Lbry.imagePath = function(file) { - return `${staticResourcesPath}/img/${file}`; -}; +Lbry.imagePath = file => `${staticResourcesPath}/img/${file}`; -Lbry.getMediaType = function(contentType, fileName) { +Lbry.getMediaType = (contentType, fileName) => { if (contentType) { return /^[^/]+/.exec(contentType)[0]; } else if (fileName) { @@ -199,14 +196,13 @@ Lbry.getMediaType = function(contentType, fileName) { return 'unknown'; }; -Lbry.getAppVersionInfo = function() { - return new Promise(resolve => { +Lbry.getAppVersionInfo = () => + new Promise(resolve => { ipcRenderer.once('version-info-received', (event, versionInfo) => { resolve(versionInfo); }); ipcRenderer.send('version-info-requested'); }); -}; /** * Wrappers for API methods to simulate missing or future behavior. Unlike the old-style stubs, @@ -217,8 +213,8 @@ Lbry.getAppVersionInfo = function() { * Returns results from the file_list API method, plus dummy entries for pending publishes. * (If a real publish with the same name is found, the pending publish will be ignored and removed.) */ -Lbry.file_list = function(params = {}) { - return new Promise((resolve, reject) => { +Lbry.file_list = params => + new Promise((resolve, reject) => { const { name, channel_name: channelName, outpoint } = params; /** @@ -252,10 +248,9 @@ Lbry.file_list = function(params = {}) { reject ); }); -}; -Lbry.claim_list_mine = function(params = {}) { - return new Promise((resolve, reject) => { +Lbry.claim_list_mine = params => + new Promise((resolve, reject) => { apiCall( 'claim_list_mine', params, @@ -274,10 +269,9 @@ Lbry.claim_list_mine = function(params = {}) { reject ); }); -}; -Lbry.resolve = function(params = {}) { - return new Promise((resolve, reject) => { +Lbry.resolve = params => + new Promise((resolve, reject) => { apiCall( 'resolve', params, @@ -292,6 +286,5 @@ Lbry.resolve = function(params = {}) { reject ); }); -}; export default lbryProxy; diff --git a/src/renderer/lbryio.js b/src/renderer/lbryio.js index 694f83ed7..a666a2b28 100644 --- a/src/renderer/lbryio.js +++ b/src/renderer/lbryio.js @@ -1,6 +1,6 @@ +import { ipcRenderer } from 'electron'; import Lbry from 'lbry'; import querystring from 'querystring'; -import { ipcRenderer } from 'electron'; const Lbryio = { enabled: true, @@ -15,7 +15,7 @@ const CONNECTION_STRING = process.env.LBRY_APP_API_URL const EXCHANGE_RATE_TIMEOUT = 20 * 60 * 1000; -Lbryio.getExchangeRates = function() { +Lbryio.getExchangeRates = () => { if ( !Lbryio.exchangeLastFetched || Date.now() - Lbryio.exchangeLastFetched > EXCHANGE_RATE_TIMEOUT @@ -33,7 +33,7 @@ Lbryio.getExchangeRates = function() { return Lbryio.exchangePromise; }; -Lbryio.call = function(resource, action, params = {}, method = 'get') { +Lbryio.call = (resource, action, params = {}, method = 'get') => { if (!Lbryio.enabled) { console.log(__('Internal API disabled')); return Promise.reject(new Error(__('LBRY internal API is disabled'))); @@ -54,7 +54,7 @@ Lbryio.call = function(resource, action, params = {}, method = 'get') { } else { error = new Error('Unknown API error signature'); } - error.response = response; // this is primarily a hack used in actions/user.js + error.response = response; // This is primarily a hack used in actions/user.js return Promise.reject(error); }); } @@ -109,7 +109,7 @@ Lbryio.setAuthToken = token => { Lbryio.getCurrentUser = () => Lbryio.call('user', 'me'); -Lbryio.authenticate = function() { +Lbryio.authenticate = () => { if (!Lbryio.enabled) { return new Promise(resolve => { resolve({ diff --git a/src/renderer/lbryuri.js b/src/renderer/lbryuri.js index d9ce508dc..3dc934770 100644 --- a/src/renderer/lbryuri.js +++ b/src/renderer/lbryuri.js @@ -28,7 +28,7 @@ Lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/; * - contentName (string): For anon claims, the name; for channel claims, the path * - channelName (string, if present): Channel name without @ */ -Lbryuri.parse = function(uri, requireProto = false) { +Lbryuri.parse = (uri, requireProto = false) => { // Break into components. Empty sub-matches are converted to null const componentsRegex = new RegExp( '^((?:lbry://)?)' + // protocol @@ -147,7 +147,7 @@ Lbryuri.parse = function(uri, requireProto = false) { * * The channelName key will accept names with or without the @ prefix. */ -Lbryuri.build = function(uriObj, includeProto = true) { +Lbryuri.build = (uriObj, includeProto = true) => { const { claimId, claimSequence, bidPosition, contentName, channelName } = uriObj; let { name, path } = uriObj; @@ -192,14 +192,14 @@ Lbryuri.build = function(uriObj, includeProto = true) { /* Takes a parseable LBRY URI and converts it to standard, canonical format (currently this just * consists of adding the lbry:// prefix if needed) */ -Lbryuri.normalize = function(uri) { +Lbryuri.normalize = uri => { if (uri.match(/pending_claim/)) return uri; const { name, path, bidPosition, claimSequence, claimId } = Lbryuri.parse(uri); return Lbryuri.build({ name, path, claimSequence, bidPosition, claimId }); }; -Lbryuri.isValid = function(uri) { +Lbryuri.isValid = uri => { let parts; try { parts = Lbryuri.parse(Lbryuri.normalize(uri)); @@ -209,12 +209,12 @@ Lbryuri.isValid = function(uri) { return parts && parts.name; }; -Lbryuri.isValidName = function(name, checkCase = true) { +Lbryuri.isValidName = (name, checkCase = true) => { const regexp = new RegExp('^[a-z0-9-]+$', checkCase ? '' : 'i'); return regexp.test(name); }; -Lbryuri.isClaimable = function(uri) { +Lbryuri.isClaimable = uri => { let parts; try { parts = Lbryuri.parse(Lbryuri.normalize(uri)); diff --git a/src/renderer/redux/actions/app.js b/src/renderer/redux/actions/app.js index 3eb7b74ed..2ecc1dcaf 100644 --- a/src/renderer/redux/actions/app.js +++ b/src/renderer/redux/actions/app.js @@ -1,23 +1,24 @@ +/* eslint-disable import/no-commonjs */ import * as ACTIONS from 'constants/action_types'; +import * as MODALS from 'constants/modal_types'; +import { ipcRenderer, remote } from 'electron'; import Lbry from 'lbry'; +import Path from 'path'; +import { doFetchRewardedContent } from 'redux/actions/content'; +import { doFetchFileInfosAndPublishedClaims } from 'redux/actions/file_info'; +import { doAuthNavigate } from 'redux/actions/navigation'; +import { doFetchDaemonSettings } from 'redux/actions/settings'; +import { doAuthenticate } from 'redux/actions/user'; +import { doBalanceSubscribe } from 'redux/actions/wallet'; import { - selectUpdateUrl, - selectUpgradeDownloadPath, - selectUpgradeDownloadItem, - selectUpgradeFilename, + selectCurrentModal, selectIsUpgradeSkipped, selectRemoteVersion, - selectCurrentModal, + selectUpdateUrl, + selectUpgradeDownloadItem, + selectUpgradeDownloadPath, + selectUpgradeFilename, } from 'redux/selectors/app'; -import { doFetchDaemonSettings } from 'redux/actions/settings'; -import { doBalanceSubscribe } from 'redux/actions/wallet'; -import { doAuthenticate } from 'redux/actions/user'; -import { doFetchFileInfosAndPublishedClaims } from 'redux/actions/file_info'; -import * as MODALS from 'constants/modal_types'; -import { doFetchRewardedContent } from 'redux/actions/content'; -import { doAuthNavigate } from 'redux/actions/navigation'; -import { remote, ipcRenderer } from 'electron'; -import Path from 'path'; const { download } = remote.require('electron-dl'); const Fs = remote.require('fs'); @@ -57,7 +58,7 @@ export function doSkipUpgrade() { } export function doStartUpgrade() { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const upgradeDownloadPath = selectUpgradeDownloadPath(state); @@ -66,7 +67,7 @@ export function doStartUpgrade() { } export function doDownloadUpgrade() { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); // Make a new directory within temp directory so the filename is guaranteed to be available const dir = Fs.mkdtempSync(remote.app.getPath('temp') + Path.sep); @@ -105,7 +106,7 @@ export function doDownloadUpgrade() { } export function doCancelUpgrade() { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const upgradeDownloadItem = selectUpgradeDownloadItem(state); @@ -128,7 +129,7 @@ export function doCancelUpgrade() { } export function doCheckUpgradeAvailable() { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); dispatch({ type: ACTIONS.CHECK_UPGRADE_START, @@ -171,7 +172,7 @@ export function doCheckUpgradeAvailable() { Initiate a timer that will check for an app upgrade every 10 minutes. */ export function doCheckUpgradeSubscribe() { - return function(dispatch) { + return dispatch => { const checkUpgradeTimer = setInterval( () => dispatch(doCheckUpgradeAvailable()), CHECK_UPGRADE_INTERVAL @@ -184,7 +185,7 @@ export function doCheckUpgradeSubscribe() { } export function doCheckDaemonVersion() { - return function(dispatch) { + return dispatch => { Lbry.version().then(({ lbrynet_version: lbrynetVersion }) => { dispatch({ type: @@ -197,7 +198,7 @@ export function doCheckDaemonVersion() { } export function doAlertError(errorList) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.OPEN_MODAL, data: { @@ -209,7 +210,7 @@ export function doAlertError(errorList) { } export function doDaemonReady() { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); dispatch(doAuthenticate()); @@ -239,7 +240,7 @@ export function doRemoveSnackBarSnack() { } export function doClearCache() { - return function() { + return () => { window.cacheStore.purge(); return Promise.resolve(); @@ -247,13 +248,13 @@ export function doClearCache() { } export function doQuit() { - return function() { + return () => { remote.app.quit(); }; } export function doChangeVolume(volume) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.VOLUME_CHANGED, data: { @@ -264,7 +265,7 @@ export function doChangeVolume(volume) { } export function doConditionalAuthNavigate(newSession) { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); if (newSession || selectCurrentModal(state) !== 'email_collection') { dispatch(doAuthNavigate()); diff --git a/src/renderer/redux/actions/availability.js b/src/renderer/redux/actions/availability.js index 2382cbbf8..01ae46ab6 100644 --- a/src/renderer/redux/actions/availability.js +++ b/src/renderer/redux/actions/availability.js @@ -1,6 +1,6 @@ // eslint-disable-next-line import/prefer-default-export export function doFetchAvailability() { - return function() { + return () => { /* this is disabled atm - Jeremy */ diff --git a/src/renderer/redux/actions/content.js b/src/renderer/redux/actions/content.js index 6a6e46f04..7ed21e4f1 100644 --- a/src/renderer/redux/actions/content.js +++ b/src/renderer/redux/actions/content.js @@ -1,31 +1,31 @@ -import { ipcRenderer } from 'electron'; import * as ACTIONS from 'constants/action_types'; +import * as MODALS from 'constants/modal_types'; import * as SETTINGS from 'constants/settings'; +import { ipcRenderer } from 'electron'; import Lbry from 'lbry'; import Lbryio from 'lbryio'; import Lbryuri from 'lbryuri'; -import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { doAlertError, doOpenModal } from 'redux/actions/app'; +import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards'; +import { selectBadgeNumber } from 'redux/selectors/app'; import { selectMyClaimsRaw } from 'redux/selectors/claims'; -import { selectBalance } from 'redux/selectors/wallet'; +import { selectResolvingUris } from 'redux/selectors/content'; +import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info'; import { makeSelectFileInfoForUri, selectDownloadingByOutpoint, selectTotalDownloadProgress, } from 'redux/selectors/file_info'; -import { selectResolvingUris } from 'redux/selectors/content'; -import { makeSelectCostInfoForUri } from 'redux/selectors/cost_info'; -import { doAlertError, doOpenModal } from 'redux/actions/app'; -import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards'; -import { selectBadgeNumber } from 'redux/selectors/app'; +import { makeSelectClientSetting } from 'redux/selectors/settings'; +import { selectBalance } from 'redux/selectors/wallet'; +import batchActions from 'util/batchActions'; import setBadge from 'util/setBadge'; import setProgressBar from 'util/setProgressBar'; -import batchActions from 'util/batchActions'; -import * as MODALS from 'constants/modal_types'; const DOWNLOAD_POLL_INTERVAL = 250; export function doResolveUris(uris) { - return function(dispatch, getState) { + return (dispatch, getState) => { const normalizedUris = uris.map(Lbryuri.normalize); const state = getState(); @@ -70,7 +70,7 @@ export function doResolveUri(uri) { } export function doFetchFeaturedUris() { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.FETCH_FEATURED_CONTENT_STARTED, }); @@ -108,7 +108,7 @@ export function doFetchFeaturedUris() { } export function doFetchRewardedContent() { - return function(dispatch) { + return dispatch => { const success = nameToClaimId => { dispatch({ type: ACTIONS.FETCH_REWARD_CONTENT_COMPLETED, @@ -134,7 +134,7 @@ export function doFetchRewardedContent() { } export function doUpdateLoadStatus(uri, outpoint) { - return function(dispatch, getState) { + return (dispatch, getState) => { Lbry.file_list({ outpoint, full_status: true, @@ -196,7 +196,7 @@ export function doUpdateLoadStatus(uri, outpoint) { } export function doStartDownload(uri, outpoint) { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); if (!outpoint) { @@ -223,7 +223,7 @@ export function doStartDownload(uri, outpoint) { } export function doDownloadFile(uri, streamInfo) { - return function(dispatch) { + return dispatch => { dispatch(doStartDownload(uri, streamInfo.outpoint)); Lbryio.call('file', 'view', { @@ -237,7 +237,7 @@ export function doDownloadFile(uri, streamInfo) { } export function doSetPlayingUri(uri) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.SET_PLAYING_URI, data: { uri }, @@ -246,7 +246,7 @@ export function doSetPlayingUri(uri) { } export function doLoadVideo(uri) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.LOADING_VIDEO_STARTED, data: { @@ -289,7 +289,7 @@ export function doLoadVideo(uri) { } export function doPurchaseUri(uri) { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const balance = selectBalance(state); const fileInfo = makeSelectFileInfoForUri(uri)(state); @@ -348,7 +348,7 @@ export function doPurchaseUri(uri) { } export function doFetchClaimsByChannel(uri, page) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED, data: { uri, page }, @@ -371,7 +371,7 @@ export function doFetchClaimsByChannel(uri, page) { } export function doFetchClaimCountByChannel(uri) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_STARTED, data: { uri }, @@ -393,7 +393,7 @@ export function doFetchClaimCountByChannel(uri) { } export function doFetchClaimListMine() { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED, }); @@ -410,14 +410,14 @@ export function doFetchClaimListMine() { } export function doPlayUri(uri) { - return function(dispatch) { + return dispatch => { dispatch(doSetPlayingUri(uri)); dispatch(doPurchaseUri(uri)); }; } export function doFetchChannelListMine() { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.FETCH_CHANNEL_LIST_MINE_STARTED, }); @@ -434,7 +434,7 @@ export function doFetchChannelListMine() { } export function doCreateChannel(name, amount) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.CREATE_CHANNEL_STARTED, }); @@ -462,8 +462,8 @@ export function doCreateChannel(name, amount) { } export function doPublish(params) { - return function(dispatch) { - return new Promise((resolve, reject) => { + return dispatch => + new Promise((resolve, reject) => { const success = claim => { resolve(claim); @@ -477,11 +477,10 @@ export function doPublish(params) { Lbry.publishDeprecated(params, null, success, failure); }); - }; } export function doAbandonClaim(txid, nout) { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const myClaims = selectMyClaimsRaw(state); const { claim_id: claimId, name } = myClaims.find( diff --git a/src/renderer/redux/actions/cost_info.js b/src/renderer/redux/actions/cost_info.js index acd0dc8cc..7e9966f05 100644 --- a/src/renderer/redux/actions/cost_info.js +++ b/src/renderer/redux/actions/cost_info.js @@ -4,7 +4,7 @@ import { selectClaimsByUri } from 'redux/selectors/claims'; // eslint-disable-next-line import/prefer-default-export export function doFetchCostInfoForUri(uri) { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const claim = selectClaimsByUri(state)[uri]; diff --git a/src/renderer/redux/actions/file_info.js b/src/renderer/redux/actions/file_info.js index d18bd2533..9ed4c9a6f 100644 --- a/src/renderer/redux/actions/file_info.js +++ b/src/renderer/redux/actions/file_info.js @@ -1,25 +1,25 @@ import * as ACTIONS from 'constants/action_types'; +import { shell } from 'electron'; import Lbry from 'lbry'; -import { doFetchClaimListMine, doAbandonClaim } from 'redux/actions/content'; +import { doCloseModal } from 'redux/actions/app'; +import { doAbandonClaim, doFetchClaimListMine } from 'redux/actions/content'; +import { doHistoryBack } from 'redux/actions/navigation'; import { selectClaimsByUri, selectIsFetchingClaimListMine, selectMyClaimsOutpoints, } from 'redux/selectors/claims'; import { - selectIsFetchingFileList, selectFileInfosByOutpoint, - selectUrisLoading, + selectIsFetchingFileList, selectTotalDownloadProgress, + selectUrisLoading, } from 'redux/selectors/file_info'; -import { doCloseModal } from 'redux/actions/app'; -import { doHistoryBack } from 'redux/actions/navigation'; -import setProgressBar from 'util/setProgressBar'; import batchActions from 'util/batchActions'; -import { shell } from 'electron'; +import setProgressBar from 'util/setProgressBar'; export function doFetchFileInfo(uri) { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const claim = selectClaimsByUri(state)[uri]; const outpoint = claim ? `${claim.txid}:${claim.nout}` : null; @@ -47,7 +47,7 @@ export function doFetchFileInfo(uri) { } export function doFileList() { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const isFetching = selectIsFetchingFileList(state); @@ -69,13 +69,13 @@ export function doFileList() { } export function doOpenFileInFolder(path) { - return function() { + return () => { shell.showItemInFolder(path); }; } export function doOpenFileInShell(path) { - return function(dispatch) { + return dispatch => { const success = shell.openItem(path); if (!success) { dispatch(doOpenFileInFolder(path)); @@ -84,7 +84,7 @@ export function doOpenFileInShell(path) { } export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); Lbry.file_delete({ @@ -92,7 +92,7 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) { delete_from_download_dir: deleteFromComputer, }); - // If the file is for a claim we published then also abandom the claim + // If the file is for a claim we published then also abandon the claim const myClaimsOutpoints = selectMyClaimsOutpoints(state); if (abandonClaim && myClaimsOutpoints.indexOf(outpoint) !== -1) { const byOutpoint = selectFileInfosByOutpoint(state); @@ -119,7 +119,7 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) { } export function doDeleteFileAndGoBack(fileInfo, deleteFromComputer, abandonClaim) { - return function(dispatch) { + return dispatch => { const actions = []; actions.push(doCloseModal()); actions.push(doHistoryBack()); @@ -129,7 +129,7 @@ export function doDeleteFileAndGoBack(fileInfo, deleteFromComputer, abandonClaim } export function doFetchFileInfosAndPublishedClaims() { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const isFetchingClaimListMine = selectIsFetchingClaimListMine(state); const isFetchingFileInfo = selectIsFetchingFileList(state); diff --git a/src/renderer/redux/actions/navigation.js b/src/renderer/redux/actions/navigation.js index ec18f9852..78e874376 100644 --- a/src/renderer/redux/actions/navigation.js +++ b/src/renderer/redux/actions/navigation.js @@ -1,9 +1,9 @@ import * as ACTIONS from 'constants/action_types'; -import { selectHistoryStack, selectHistoryIndex } from 'redux/selectors/navigation'; +import { selectHistoryIndex, selectHistoryStack } from 'redux/selectors/navigation'; import { toQueryString } from 'util/query_params'; export function doNavigate(path, params = {}, options = {}) { - return function(dispatch) { + return dispatch => { if (!path) { return; } @@ -23,7 +23,7 @@ export function doNavigate(path, params = {}, options = {}) { } export function doAuthNavigate(pathAfterAuth = null, params = {}) { - return function(dispatch) { + return dispatch => { if (pathAfterAuth) { dispatch({ type: ACTIONS.CHANGE_AFTER_AUTH_PATH, @@ -47,19 +47,15 @@ export function doHistoryTraverse(dispatch, state, modifier) { } export function doHistoryBack() { - return function(dispatch, getState) { - return doHistoryTraverse(dispatch, getState(), -1); - }; + return (dispatch, getState) => doHistoryTraverse(dispatch, getState(), -1); } export function doHistoryForward() { - return function(dispatch, getState) { - return doHistoryTraverse(dispatch, getState(), 1); - }; + return (dispatch, getState) => doHistoryTraverse(dispatch, getState(), 1); } export function doRecordScroll(scroll) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.WINDOW_SCROLLED, data: { scrollY: scroll }, diff --git a/src/renderer/redux/actions/rewards.js b/src/renderer/redux/actions/rewards.js index 4c4a278cd..e5067f5b0 100644 --- a/src/renderer/redux/actions/rewards.js +++ b/src/renderer/redux/actions/rewards.js @@ -1,12 +1,12 @@ import * as ACTIONS from 'constants/action_types'; import * as MODALS from 'constants/modal_types'; import Lbryio from 'lbryio'; -import rewards from 'rewards'; import { selectUnclaimedRewardsByType } from 'redux/selectors/rewards'; import { selectUserIsRewardApproved } from 'redux/selectors/user'; +import rewards from 'rewards'; export function doRewardList() { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.FETCH_REWARDS_STARTED, }); @@ -28,7 +28,7 @@ export function doRewardList() { } export function doClaimRewardType(rewardType) { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const rewardsByType = selectUnclaimedRewardsByType(state); const reward = rewardsByType[rewardType]; @@ -80,7 +80,7 @@ export function doClaimRewardType(rewardType) { } export function doClaimEligiblePurchaseRewards() { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const rewardsByType = selectUnclaimedRewardsByType(state); const userIsRewardApproved = selectUserIsRewardApproved(state); @@ -100,7 +100,7 @@ export function doClaimEligiblePurchaseRewards() { } export function doClaimRewardClearError(reward) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.CLAIM_REWARD_CLEAR_ERROR, data: { reward }, diff --git a/src/renderer/redux/actions/search.js b/src/renderer/redux/actions/search.js index 66de54ef1..277b5cbe4 100644 --- a/src/renderer/redux/actions/search.js +++ b/src/renderer/redux/actions/search.js @@ -7,7 +7,7 @@ import batchActions from 'util/batchActions'; // eslint-disable-next-line import/prefer-default-export export function doSearch(rawQuery) { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const page = selectCurrentPage(state); diff --git a/src/renderer/redux/actions/settings.js b/src/renderer/redux/actions/settings.js index 54af9e300..7f0209132 100644 --- a/src/renderer/redux/actions/settings.js +++ b/src/renderer/redux/actions/settings.js @@ -6,7 +6,7 @@ import Http from 'http'; import Lbry from 'lbry'; export function doFetchDaemonSettings() { - return function(dispatch) { + return dispatch => { Lbry.settings_get().then(settings => { dispatch({ type: ACTIONS.DAEMON_SETTINGS_RECEIVED, @@ -19,7 +19,7 @@ export function doFetchDaemonSettings() { } export function doSetDaemonSetting(key, value) { - return function(dispatch) { + return dispatch => { const newSettings = {}; newSettings[key] = value; Lbry.settings_set(newSettings).then(newSettings); @@ -45,14 +45,14 @@ export function doSetClientSetting(key, value) { } export function doGetThemes() { - return function(dispatch) { + return dispatch => { const themes = ['light', 'dark']; dispatch(doSetClientSetting(SETTINGS.THEMES, themes)); }; } export function doDownloadLanguage(langFile) { - return function(dispatch) { + return dispatch => { const destinationPath = `${app.i18n.directory}/${langFile}`; const language = langFile.replace('.json', ''); const errorHandler = () => { @@ -105,7 +105,7 @@ export function doDownloadLanguage(langFile) { } export function doDownloadLanguages() { - return function() { + return () => { // temporarily disable i18n so I can get a working build out -- Jeremy // if (!Fs.existsSync(app.i18n.directory)) { // Fs.mkdirSync(app.i18n.directory); @@ -135,7 +135,7 @@ export function doDownloadLanguages() { } export function doChangeLanguage(language) { - return function(dispatch) { + return dispatch => { dispatch(doSetClientSetting(SETTINGS.LANGUAGE, language)); app.i18n.setLocale(language); }; diff --git a/src/renderer/redux/actions/user.js b/src/renderer/redux/actions/user.js index 32d9fafc8..f0506ff65 100644 --- a/src/renderer/redux/actions/user.js +++ b/src/renderer/redux/actions/user.js @@ -2,12 +2,12 @@ import * as ACTIONS from 'constants/action_types'; import * as MODALS from 'constants/modal_types'; import Lbryio from 'lbryio'; import { doOpenModal, doShowSnackBar } from 'redux/actions/app'; -import { doRewardList, doClaimRewardType } from 'redux/actions/rewards'; +import { doClaimRewardType, doRewardList } from 'redux/actions/rewards'; import { selectEmailToVerify } from 'redux/selectors/user'; import rewards from 'rewards'; export function doFetchInviteStatus() { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.USER_INVITE_STATUS_FETCH_STARTED, }); @@ -32,7 +32,7 @@ export function doFetchInviteStatus() { } export function doAuthenticate() { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.AUTHENTICATION_STARTED, }); @@ -56,7 +56,7 @@ export function doAuthenticate() { } export function doUserFetch() { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.USER_FETCH_STARTED, }); @@ -79,7 +79,7 @@ export function doUserFetch() { } export function doUserEmailNew(email) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.USER_EMAIL_NEW_STARTED, email, @@ -124,7 +124,7 @@ export function doUserEmailVerifyFailure(error) { } export function doUserEmailVerify(verificationToken, recaptcha) { - return function(dispatch, getState) { + return (dispatch, getState) => { const email = selectEmailToVerify(getState()); dispatch({ @@ -160,7 +160,7 @@ export function doUserEmailVerify(verificationToken, recaptcha) { } export function doUserIdentityVerify(stripeToken) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.USER_IDENTITY_VERIFY_STARTED, token: stripeToken, @@ -188,7 +188,7 @@ export function doUserIdentityVerify(stripeToken) { } export function doFetchAccessToken() { - return function(dispatch) { + return dispatch => { const success = token => dispatch({ type: ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS, @@ -199,7 +199,7 @@ export function doFetchAccessToken() { } export function doUserInviteNew(email) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.USER_INVITE_NEW_STARTED, }); diff --git a/src/renderer/redux/actions/wallet.js b/src/renderer/redux/actions/wallet.js index 60ffbef84..9976c98ff 100644 --- a/src/renderer/redux/actions/wallet.js +++ b/src/renderer/redux/actions/wallet.js @@ -1,16 +1,16 @@ import * as ACTIONS from 'constants/action_types'; +import * as MODALS from 'constants/modal_types'; import Lbry from 'lbry'; -import { - selectDraftTransaction, - selectDraftTransactionAmount, - selectBalance, -} from 'redux/selectors/wallet'; import { doOpenModal, doShowSnackBar } from 'redux/actions/app'; import { doNavigate } from 'redux/actions/navigation'; -import * as MODALS from 'constants/modal_types'; +import { + selectBalance, + selectDraftTransaction, + selectDraftTransactionAmount, +} from 'redux/selectors/wallet'; export function doUpdateBalance() { - return function(dispatch) { + return dispatch => { Lbry.wallet_balance().then(balance => dispatch({ type: ACTIONS.UPDATE_BALANCE, @@ -23,14 +23,14 @@ export function doUpdateBalance() { } export function doBalanceSubscribe() { - return function(dispatch) { + return dispatch => { dispatch(doUpdateBalance()); setInterval(() => dispatch(doUpdateBalance()), 5000); }; } export function doFetchTransactions() { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.FETCH_TRANSACTIONS_STARTED, }); @@ -47,7 +47,7 @@ export function doFetchTransactions() { } export function doFetchBlock(height) { - return function(dispatch) { + return dispatch => { Lbry.block_show({ height }).then(block => { dispatch({ type: ACTIONS.FETCH_BLOCK_SUCCESS, @@ -58,7 +58,7 @@ export function doFetchBlock(height) { } export function doGetNewAddress() { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.GET_NEW_ADDRESS_STARTED, }); @@ -74,7 +74,7 @@ export function doGetNewAddress() { } export function doCheckAddressIsMine(address) { - return function(dispatch) { + return dispatch => { dispatch({ type: ACTIONS.CHECK_ADDRESS_IS_MINE_STARTED, }); @@ -90,7 +90,7 @@ export function doCheckAddressIsMine(address) { } export function doSendDraftTransaction() { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const draftTx = selectDraftTransaction(state); const balance = selectBalance(state); @@ -156,7 +156,7 @@ export function doSetDraftTransactionAddress(address) { } export function doSendSupport(amount, claimId, uri) { - return function(dispatch, getState) { + return (dispatch, getState) => { const state = getState(); const balance = selectBalance(state); diff --git a/src/renderer/redux/reducers/app.js b/src/renderer/redux/reducers/app.js index c8a821fa8..87a588f3c 100644 --- a/src/renderer/redux/reducers/app.js +++ b/src/renderer/redux/reducers/app.js @@ -3,7 +3,7 @@ import * as ACTIONS from 'constants/action_types'; import * as MODALS from 'constants/modal_types'; -const { remote } = require('electron'); +import { remote } from 'electron'; const win = remote.BrowserWindow.getFocusedWindow(); @@ -56,48 +56,42 @@ const defaultState: AppState = { snackBar: undefined, }; -reducers[ACTIONS.DAEMON_READY] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.DAEMON_READY] = state => + Object.assign({}, state, { daemonReady: true, }); -}; -reducers[ACTIONS.DAEMON_VERSION_MATCH] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.DAEMON_VERSION_MATCH] = state => + Object.assign({}, state, { daemonVersionMatched: true, }); -}; -reducers[ACTIONS.DAEMON_VERSION_MISMATCH] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.DAEMON_VERSION_MISMATCH] = state => + Object.assign({}, state, { daemonVersionMatched: false, modal: MODALS.INCOMPATIBLE_DAEMON, }); -}; -reducers[ACTIONS.UPGRADE_CANCELLED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.UPGRADE_CANCELLED] = state => + Object.assign({}, state, { downloadProgress: null, upgradeDownloadComplete: false, modal: null, }); -}; -reducers[ACTIONS.UPGRADE_DOWNLOAD_COMPLETED] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.UPGRADE_DOWNLOAD_COMPLETED] = (state, action) => + Object.assign({}, state, { downloadPath: action.data.path, upgradeDownloading: false, upgradeDownloadCompleted: true, }); -}; -reducers[ACTIONS.UPGRADE_DOWNLOAD_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.UPGRADE_DOWNLOAD_STARTED] = state => + Object.assign({}, state, { upgradeDownloading: true, }); -}; -reducers[ACTIONS.SKIP_UPGRADE] = function(state) { +reducers[ACTIONS.SKIP_UPGRADE] = state => { sessionStorage.setItem('upgradeSkipped', 'true'); return Object.assign({}, state, { @@ -106,46 +100,40 @@ reducers[ACTIONS.SKIP_UPGRADE] = function(state) { }); }; -reducers[ACTIONS.UPDATE_VERSION] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.UPDATE_VERSION] = (state, action) => + Object.assign({}, state, { version: action.data.version, }); -}; -reducers[ACTIONS.CHECK_UPGRADE_SUCCESS] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.CHECK_UPGRADE_SUCCESS] = (state, action) => + Object.assign({}, state, { isUpgradeAvailable: action.data.upgradeAvailable, remoteVersion: action.data.remoteVersion, }); -}; -reducers[ACTIONS.CHECK_UPGRADE_SUBSCRIBE] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.CHECK_UPGRADE_SUBSCRIBE] = (state, action) => + Object.assign({}, state, { checkUpgradeTimer: action.data.checkUpgradeTimer, }); -}; -reducers[ACTIONS.OPEN_MODAL] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.OPEN_MODAL] = (state, action) => + Object.assign({}, state, { modal: action.data.modal, modalProps: action.data.modalProps || {}, }); -}; -reducers[ACTIONS.CLOSE_MODAL] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.CLOSE_MODAL] = state => + Object.assign({}, state, { modal: undefined, modalProps: {}, }); -}; -reducers[ACTIONS.UPGRADE_DOWNLOAD_PROGRESSED] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.UPGRADE_DOWNLOAD_PROGRESSED] = (state, action) => + Object.assign({}, state, { downloadProgress: action.data.percent, }); -}; -reducers[ACTIONS.SHOW_SNACKBAR] = function(state, action) { +reducers[ACTIONS.SHOW_SNACKBAR] = (state, action) => { const { message, linkText, linkTarget, isError } = action.data; const snackBar = Object.assign({}, state.snackBar); const snacks = Object.assign([], snackBar.snacks); @@ -164,7 +152,7 @@ reducers[ACTIONS.SHOW_SNACKBAR] = function(state, action) { }); }; -reducers[ACTIONS.REMOVE_SNACKBAR_SNACK] = function(state) { +reducers[ACTIONS.REMOVE_SNACKBAR_SNACK] = state => { const snackBar = Object.assign({}, state.snackBar); const snacks = Object.assign([], snackBar.snacks); snacks.shift(); @@ -178,7 +166,7 @@ reducers[ACTIONS.REMOVE_SNACKBAR_SNACK] = function(state) { }); }; -reducers[ACTIONS.DOWNLOADING_COMPLETED] = function(state) { +reducers[ACTIONS.DOWNLOADING_COMPLETED] = state => { const { badgeNumber } = state; // Don't update the badge number if the window is focused @@ -189,17 +177,15 @@ reducers[ACTIONS.DOWNLOADING_COMPLETED] = function(state) { }); }; -reducers[ACTIONS.WINDOW_FOCUSED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.WINDOW_FOCUSED] = state => + Object.assign({}, state, { badgeNumber: 0, }); -}; -reducers[ACTIONS.VOLUME_CHANGED] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.VOLUME_CHANGED] = (state, action) => + Object.assign({}, state, { volume: action.data.volume, }); -}; export default function reducer(state: AppState = defaultState, action: any) { const handler = reducers[action.type]; diff --git a/src/renderer/redux/reducers/availability.js b/src/renderer/redux/reducers/availability.js index 48133ff50..27648ad4a 100644 --- a/src/renderer/redux/reducers/availability.js +++ b/src/renderer/redux/reducers/availability.js @@ -3,7 +3,7 @@ import * as ACTIONS from 'constants/action_types'; const reducers = {}; const defaultState = {}; -reducers[ACTIONS.FETCH_AVAILABILITY_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_AVAILABILITY_STARTED] = (state, action) => { const { uri } = action.data; const newFetching = Object.assign({}, state.fetching); @@ -14,7 +14,7 @@ reducers[ACTIONS.FETCH_AVAILABILITY_STARTED] = function(state, action) { }); }; -reducers[ACTIONS.FETCH_AVAILABILITY_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_AVAILABILITY_COMPLETED] = (state, action) => { const { uri, availability } = action.data; const newFetching = Object.assign({}, state.fetching); diff --git a/src/renderer/redux/reducers/claims.js b/src/renderer/redux/reducers/claims.js index 6547dd5f4..73eee7815 100644 --- a/src/renderer/redux/reducers/claims.js +++ b/src/renderer/redux/reducers/claims.js @@ -4,7 +4,7 @@ const reducers = {}; const defaultState = {}; -reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = function(state, action) { +reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = (state, action) => { const { resolveInfo } = action.data; const byUri = Object.assign({}, state.claimsByUri); const byId = Object.assign({}, state.byId); @@ -33,13 +33,12 @@ reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = function(state, action) { }); }; -reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED] = state => + Object.assign({}, state, { isFetchingClaimListMine: true, }); -}; -reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state, action) => { const { claims } = action.data; const byId = Object.assign({}, state.byId); const pendingById = Object.assign({}, state.pendingById); @@ -72,11 +71,10 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) { }); }; -reducers[ACTIONS.FETCH_CHANNEL_LIST_MINE_STARTED] = function(state) { - return Object.assign({}, state, { fetchingMyChannels: true }); -}; +reducers[ACTIONS.FETCH_CHANNEL_LIST_MINE_STARTED] = state => + Object.assign({}, state, { fetchingMyChannels: true }); -reducers[ACTIONS.FETCH_CHANNEL_LIST_MINE_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_CHANNEL_LIST_MINE_COMPLETED] = (state, action) => { const { claims } = action.data; const myChannelClaims = new Set(state.myChannelClaims); const byId = Object.assign({}, state.byId); @@ -93,7 +91,7 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_MINE_COMPLETED] = function(state, action) { }); }; -reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED] = (state, action) => { const { uri, page } = action.data; const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims); @@ -104,7 +102,7 @@ reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) { }); }; -reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED] = (state, action) => { const { uri, claims, page } = action.data; const claimsByChannel = Object.assign({}, state.claimsByChannel); @@ -134,7 +132,7 @@ reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) { }); }; -reducers[ACTIONS.ABANDON_CLAIM_STARTED] = function(state, action) { +reducers[ACTIONS.ABANDON_CLAIM_STARTED] = (state, action) => { const { claimId } = action.data; const abandoningById = Object.assign({}, state.abandoningById); @@ -145,7 +143,7 @@ reducers[ACTIONS.ABANDON_CLAIM_STARTED] = function(state, action) { }); }; -reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = function(state, action) { +reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = (state, action) => { const { claimId } = action.data; const byId = Object.assign({}, state.byId); const claimsByUri = Object.assign({}, state.claimsByUri); @@ -164,7 +162,7 @@ reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = function(state, action) { }); }; -reducers[ACTIONS.CREATE_CHANNEL_COMPLETED] = function(state, action) { +reducers[ACTIONS.CREATE_CHANNEL_COMPLETED] = (state, action) => { const { channelClaim } = action.data; const byId = Object.assign({}, state.byId); const myChannelClaims = new Set(state.myChannelClaims); diff --git a/src/renderer/redux/reducers/content.js b/src/renderer/redux/reducers/content.js index b16c911b1..e5242b599 100644 --- a/src/renderer/redux/reducers/content.js +++ b/src/renderer/redux/reducers/content.js @@ -7,13 +7,12 @@ const defaultState = { channelClaimCounts: {}, }; -reducers[ACTIONS.FETCH_FEATURED_CONTENT_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.FETCH_FEATURED_CONTENT_STARTED] = state => + Object.assign({}, state, { fetchingFeaturedContent: true, }); -}; -reducers[ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED] = (state, action) => { const { uris, success } = action.data; return Object.assign({}, state, { @@ -23,7 +22,7 @@ reducers[ACTIONS.FETCH_FEATURED_CONTENT_COMPLETED] = function(state, action) { }); }; -reducers[ACTIONS.FETCH_REWARD_CONTENT_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_REWARD_CONTENT_COMPLETED] = (state, action) => { const { claimIds } = action.data; return Object.assign({}, state, { @@ -31,7 +30,7 @@ reducers[ACTIONS.FETCH_REWARD_CONTENT_COMPLETED] = function(state, action) { }); }; -reducers[ACTIONS.RESOLVE_URIS_STARTED] = function(state, action) { +reducers[ACTIONS.RESOLVE_URIS_STARTED] = (state, action) => { const { uris } = action.data; const oldResolving = state.resolvingUris || []; @@ -48,7 +47,7 @@ reducers[ACTIONS.RESOLVE_URIS_STARTED] = function(state, action) { }); }; -reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = function(state, action) { +reducers[ACTIONS.RESOLVE_URIS_COMPLETED] = (state, action) => { const { resolveInfo } = action.data; const channelClaimCounts = Object.assign({}, state.channelClaimCounts); @@ -69,7 +68,7 @@ reducers[ACTIONS.SET_PLAYING_URI] = (state, action) => playingUri: action.data.uri, }); -reducers[ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = (state, action) => { const channelClaimCounts = Object.assign({}, state.channelClaimCounts); const { uri, totalClaims } = action.data; diff --git a/src/renderer/redux/reducers/cost_info.js b/src/renderer/redux/reducers/cost_info.js index 18c6214ac..4137bb83f 100644 --- a/src/renderer/redux/reducers/cost_info.js +++ b/src/renderer/redux/reducers/cost_info.js @@ -3,7 +3,7 @@ import * as ACTIONS from 'constants/action_types'; const reducers = {}; const defaultState = {}; -reducers[ACTIONS.FETCH_COST_INFO_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_COST_INFO_STARTED] = (state, action) => { const { uri } = action.data; const newFetching = Object.assign({}, state.fetching); newFetching[uri] = true; @@ -13,7 +13,7 @@ reducers[ACTIONS.FETCH_COST_INFO_STARTED] = function(state, action) { }); }; -reducers[ACTIONS.FETCH_COST_INFO_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_COST_INFO_COMPLETED] = (state, action) => { const { uri, costInfo } = action.data; const newByUri = Object.assign({}, state.byUri); const newFetching = Object.assign({}, state.fetching); diff --git a/src/renderer/redux/reducers/file_info.js b/src/renderer/redux/reducers/file_info.js index 25ae15546..0d9ed2431 100644 --- a/src/renderer/redux/reducers/file_info.js +++ b/src/renderer/redux/reducers/file_info.js @@ -3,13 +3,12 @@ import * as ACTIONS from 'constants/action_types'; const reducers = {}; const defaultState = {}; -reducers[ACTIONS.FILE_LIST_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.FILE_LIST_STARTED] = state => + Object.assign({}, state, { isFetchingFileList: true, }); -}; -reducers[ACTIONS.FILE_LIST_SUCCEEDED] = function(state, action) { +reducers[ACTIONS.FILE_LIST_SUCCEEDED] = (state, action) => { const { fileInfos } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); const pendingByOutpoint = Object.assign({}, state.pendingByOutpoint); @@ -27,7 +26,7 @@ reducers[ACTIONS.FILE_LIST_SUCCEEDED] = function(state, action) { }); }; -reducers[ACTIONS.FETCH_FILE_INFO_STARTED] = function(state, action) { +reducers[ACTIONS.FETCH_FILE_INFO_STARTED] = (state, action) => { const { outpoint } = action.data; const newFetching = Object.assign({}, state.fetching); @@ -38,7 +37,7 @@ reducers[ACTIONS.FETCH_FILE_INFO_STARTED] = function(state, action) { }); }; -reducers[ACTIONS.FETCH_FILE_INFO_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_FILE_INFO_COMPLETED] = (state, action) => { const { fileInfo, outpoint } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); @@ -53,7 +52,7 @@ reducers[ACTIONS.FETCH_FILE_INFO_COMPLETED] = function(state, action) { }); }; -reducers[ACTIONS.DOWNLOADING_STARTED] = function(state, action) { +reducers[ACTIONS.DOWNLOADING_STARTED] = (state, action) => { const { uri, outpoint, fileInfo } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); @@ -71,7 +70,7 @@ reducers[ACTIONS.DOWNLOADING_STARTED] = function(state, action) { }); }; -reducers[ACTIONS.DOWNLOADING_PROGRESSED] = function(state, action) { +reducers[ACTIONS.DOWNLOADING_PROGRESSED] = (state, action) => { const { outpoint, fileInfo } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); @@ -86,7 +85,7 @@ reducers[ACTIONS.DOWNLOADING_PROGRESSED] = function(state, action) { }); }; -reducers[ACTIONS.DOWNLOADING_COMPLETED] = function(state, action) { +reducers[ACTIONS.DOWNLOADING_COMPLETED] = (state, action) => { const { outpoint, fileInfo } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); @@ -101,7 +100,7 @@ reducers[ACTIONS.DOWNLOADING_COMPLETED] = function(state, action) { }); }; -reducers[ACTIONS.FILE_DELETE] = function(state, action) { +reducers[ACTIONS.FILE_DELETE] = (state, action) => { const { outpoint } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); @@ -116,7 +115,7 @@ reducers[ACTIONS.FILE_DELETE] = function(state, action) { }); }; -reducers[ACTIONS.LOADING_VIDEO_STARTED] = function(state, action) { +reducers[ACTIONS.LOADING_VIDEO_STARTED] = (state, action) => { const { uri } = action.data; const newLoading = Object.assign({}, state.urisLoading); @@ -128,7 +127,7 @@ reducers[ACTIONS.LOADING_VIDEO_STARTED] = function(state, action) { }); }; -reducers[ACTIONS.LOADING_VIDEO_FAILED] = function(state, action) { +reducers[ACTIONS.LOADING_VIDEO_FAILED] = (state, action) => { const { uri } = action.data; const newLoading = Object.assign({}, state.urisLoading); @@ -140,7 +139,7 @@ reducers[ACTIONS.LOADING_VIDEO_FAILED] = function(state, action) { }); }; -reducers[ACTIONS.FETCH_DATE] = function(state, action) { +reducers[ACTIONS.FETCH_DATE] = (state, action) => { const { time } = action.data; if (time) { return Object.assign({}, state, { diff --git a/src/renderer/redux/reducers/navigation.js b/src/renderer/redux/reducers/navigation.js index 581fd52d2..e4544b4cc 100644 --- a/src/renderer/redux/reducers/navigation.js +++ b/src/renderer/redux/reducers/navigation.js @@ -14,7 +14,7 @@ const defaultState = { stack: [], }; -reducers[ACTIONS.DAEMON_READY] = function(state) { +reducers[ACTIONS.DAEMON_READY] = state => { const { currentPath } = state; return Object.assign({}, state, { @@ -22,11 +22,10 @@ reducers[ACTIONS.DAEMON_READY] = function(state) { }); }; -reducers[ACTIONS.CHANGE_AFTER_AUTH_PATH] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.CHANGE_AFTER_AUTH_PATH] = (state, action) => + Object.assign({}, state, { pathAfterAuth: action.data.path, }); -}; reducers[ACTIONS.HISTORY_NAVIGATE] = (state, action) => { const { stack, index } = state; diff --git a/src/renderer/redux/reducers/rewards.js b/src/renderer/redux/reducers/rewards.js index f9a108f12..f2f42c004 100644 --- a/src/renderer/redux/reducers/rewards.js +++ b/src/renderer/redux/reducers/rewards.js @@ -9,13 +9,12 @@ const defaultState = { claimErrorsByType: {}, }; -reducers[ACTIONS.FETCH_REWARDS_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.FETCH_REWARDS_STARTED] = state => + Object.assign({}, state, { fetching: true, }); -}; -reducers[ACTIONS.FETCH_REWARDS_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_REWARDS_COMPLETED] = (state, action) => { const { userRewards } = action.data; const unclaimedRewards = {}; @@ -55,13 +54,13 @@ function setClaimRewardState(state, reward, isClaiming, errorMessage = '') { }); } -reducers[ACTIONS.CLAIM_REWARD_STARTED] = function(state, action) { +reducers[ACTIONS.CLAIM_REWARD_STARTED] = (state, action) => { const { reward } = action.data; return setClaimRewardState(state, reward, true, ''); }; -reducers[ACTIONS.CLAIM_REWARD_SUCCESS] = function(state, action) { +reducers[ACTIONS.CLAIM_REWARD_SUCCESS] = (state, action) => { const { reward } = action.data; const unclaimedRewardsByType = Object.assign({}, state.unclaimedRewardsByType); @@ -83,13 +82,13 @@ reducers[ACTIONS.CLAIM_REWARD_SUCCESS] = function(state, action) { return setClaimRewardState(newState, newReward, false, ''); }; -reducers[ACTIONS.CLAIM_REWARD_FAILURE] = function(state, action) { +reducers[ACTIONS.CLAIM_REWARD_FAILURE] = (state, action) => { const { reward, error } = action.data; return setClaimRewardState(state, reward, false, error ? error.message : ''); }; -reducers[ACTIONS.CLAIM_REWARD_CLEAR_ERROR] = function(state, action) { +reducers[ACTIONS.CLAIM_REWARD_CLEAR_ERROR] = (state, action) => { const { reward } = action.data; return setClaimRewardState(state, reward, state.claimPendingByType[reward.reward_type], ''); diff --git a/src/renderer/redux/reducers/search.js b/src/renderer/redux/reducers/search.js index 00764c2b7..b3a0754e4 100644 --- a/src/renderer/redux/reducers/search.js +++ b/src/renderer/redux/reducers/search.js @@ -6,13 +6,12 @@ const defaultState = { searching: false, }; -reducers[ACTIONS.SEARCH_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.SEARCH_STARTED] = state => + Object.assign({}, state, { searching: true, }); -}; -reducers[ACTIONS.SEARCH_COMPLETED] = function(state, action) { +reducers[ACTIONS.SEARCH_COMPLETED] = (state, action) => { const { query, uris } = action.data; return Object.assign({}, state, { @@ -21,11 +20,10 @@ reducers[ACTIONS.SEARCH_COMPLETED] = function(state, action) { }); }; -reducers[ACTIONS.SEARCH_CANCELLED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.SEARCH_CANCELLED] = state => + Object.assign({}, state, { searching: false, }); -}; export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; diff --git a/src/renderer/redux/reducers/settings.js b/src/renderer/redux/reducers/settings.js index b3cf5794a..914404bb1 100644 --- a/src/renderer/redux/reducers/settings.js +++ b/src/renderer/redux/reducers/settings.js @@ -1,6 +1,6 @@ import * as ACTIONS from 'constants/action_types'; -import * as SETTINGS from 'constants/settings'; import LANGUAGES from 'constants/languages'; +import * as SETTINGS from 'constants/settings'; function getLocalStorageSetting(setting, fallback) { const localStorageVal = localStorage.getItem(`setting_${setting}`); @@ -27,13 +27,12 @@ const defaultState = { languages: {}, }; -reducers[ACTIONS.DAEMON_SETTINGS_RECEIVED] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.DAEMON_SETTINGS_RECEIVED] = (state, action) => + Object.assign({}, state, { daemonSettings: action.data.settings, }); -}; -reducers[ACTIONS.CLIENT_SETTING_CHANGED] = function(state, action) { +reducers[ACTIONS.CLIENT_SETTING_CHANGED] = (state, action) => { const { key, value } = action.data; const clientSettings = Object.assign({}, state.clientSettings); @@ -47,7 +46,7 @@ reducers[ACTIONS.CLIENT_SETTING_CHANGED] = function(state, action) { }); }; -reducers[ACTIONS.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) { +reducers[ACTIONS.DOWNLOAD_LANGUAGE_SUCCEEDED] = (state, action) => { const languages = Object.assign({}, state.languages); const { language } = action.data; @@ -62,7 +61,7 @@ reducers[ACTIONS.DOWNLOAD_LANGUAGE_SUCCEEDED] = function(state, action) { return Object.assign({}, state, { languages }); }; -reducers[ACTIONS.DOWNLOAD_LANGUAGE_FAILED] = function(state, action) { +reducers[ACTIONS.DOWNLOAD_LANGUAGE_FAILED] = (state, action) => { const languages = Object.assign({}, state.languages); delete languages[action.data.language]; return Object.assign({}, state, { languages }); diff --git a/src/renderer/redux/reducers/user.js b/src/renderer/redux/reducers/user.js index be8c5f1c7..f616dd1d1 100644 --- a/src/renderer/redux/reducers/user.js +++ b/src/renderer/redux/reducers/user.js @@ -16,59 +16,52 @@ const defaultState = { user: undefined, }; -reducers[ACTIONS.AUTHENTICATION_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.AUTHENTICATION_STARTED] = state => + Object.assign({}, state, { authenticationIsPending: true, userIsPending: true, user: defaultState.user, }); -}; -reducers[ACTIONS.AUTHENTICATION_SUCCESS] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.AUTHENTICATION_SUCCESS] = (state, action) => + Object.assign({}, state, { authenticationIsPending: false, userIsPending: false, user: action.data.user, }); -}; -reducers[ACTIONS.AUTHENTICATION_FAILURE] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.AUTHENTICATION_FAILURE] = state => + Object.assign({}, state, { authenticationIsPending: false, userIsPending: false, user: null, }); -}; -reducers[ACTIONS.USER_FETCH_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_FETCH_STARTED] = state => + Object.assign({}, state, { userIsPending: true, user: defaultState.user, }); -}; -reducers[ACTIONS.USER_FETCH_SUCCESS] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_FETCH_SUCCESS] = (state, action) => + Object.assign({}, state, { userIsPending: false, user: action.data.user, }); -}; -reducers[ACTIONS.USER_FETCH_FAILURE] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_FETCH_FAILURE] = state => + Object.assign({}, state, { userIsPending: true, user: null, }); -}; -reducers[ACTIONS.USER_EMAIL_NEW_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_EMAIL_NEW_STARTED] = state => + Object.assign({}, state, { emailNewIsPending: true, emailNewErrorMessage: '', }); -}; -reducers[ACTIONS.USER_EMAIL_NEW_SUCCESS] = function(state, action) { +reducers[ACTIONS.USER_EMAIL_NEW_SUCCESS] = (state, action) => { const user = Object.assign({}, state.user); user.primary_email = action.data.email; return Object.assign({}, state, { @@ -78,28 +71,25 @@ reducers[ACTIONS.USER_EMAIL_NEW_SUCCESS] = function(state, action) { }); }; -reducers[ACTIONS.USER_EMAIL_NEW_EXISTS] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_EMAIL_NEW_EXISTS] = (state, action) => + Object.assign({}, state, { emailToVerify: action.data.email, emailNewIsPending: false, }); -}; -reducers[ACTIONS.USER_EMAIL_NEW_FAILURE] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_EMAIL_NEW_FAILURE] = (state, action) => + Object.assign({}, state, { emailNewIsPending: false, emailNewErrorMessage: action.data.error, }); -}; -reducers[ACTIONS.USER_EMAIL_VERIFY_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_EMAIL_VERIFY_STARTED] = state => + Object.assign({}, state, { emailVerifyIsPending: true, emailVerifyErrorMessage: '', }); -}; -reducers[ACTIONS.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) { +reducers[ACTIONS.USER_EMAIL_VERIFY_SUCCESS] = (state, action) => { const user = Object.assign({}, state.user); user.primary_email = action.data.email; return Object.assign({}, state, { @@ -109,36 +99,32 @@ reducers[ACTIONS.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) { }); }; -reducers[ACTIONS.USER_EMAIL_VERIFY_FAILURE] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_EMAIL_VERIFY_FAILURE] = (state, action) => + Object.assign({}, state, { emailVerifyIsPending: false, emailVerifyErrorMessage: action.data.error, }); -}; -reducers[ACTIONS.USER_IDENTITY_VERIFY_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_IDENTITY_VERIFY_STARTED] = state => + Object.assign({}, state, { identityVerifyIsPending: true, identityVerifyErrorMessage: '', }); -}; -reducers[ACTIONS.USER_IDENTITY_VERIFY_SUCCESS] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_IDENTITY_VERIFY_SUCCESS] = (state, action) => + Object.assign({}, state, { identityVerifyIsPending: false, identityVerifyErrorMessage: '', user: action.data.user, }); -}; -reducers[ACTIONS.USER_IDENTITY_VERIFY_FAILURE] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_IDENTITY_VERIFY_FAILURE] = (state, action) => + Object.assign({}, state, { identityVerifyIsPending: false, identityVerifyErrorMessage: action.data.error, }); -}; -reducers[ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS] = function(state, action) { +reducers[ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS] = (state, action) => { const { token } = action.data; return Object.assign({}, state, { @@ -146,48 +132,42 @@ reducers[ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS] = function(state, action) { }); }; -reducers[ACTIONS.USER_INVITE_STATUS_FETCH_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_INVITE_STATUS_FETCH_STARTED] = state => + Object.assign({}, state, { inviteStatusIsPending: true, }); -}; -reducers[ACTIONS.USER_INVITE_STATUS_FETCH_SUCCESS] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_INVITE_STATUS_FETCH_SUCCESS] = (state, action) => + Object.assign({}, state, { inviteStatusIsPending: false, invitesRemaining: action.data.invitesRemaining, invitees: action.data.invitees, }); -}; -reducers[ACTIONS.USER_INVITE_NEW_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_INVITE_NEW_STARTED] = state => + Object.assign({}, state, { inviteNewIsPending: true, inviteNewErrorMessage: '', }); -}; -reducers[ACTIONS.USER_INVITE_NEW_SUCCESS] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_INVITE_NEW_SUCCESS] = state => + Object.assign({}, state, { inviteNewIsPending: false, inviteNewErrorMessage: '', }); -}; -reducers[ACTIONS.USER_INVITE_NEW_FAILURE] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_INVITE_NEW_FAILURE] = (state, action) => + Object.assign({}, state, { inviteNewIsPending: false, inviteNewErrorMessage: action.data.error.message, }); -}; -reducers[ACTIONS.USER_INVITE_STATUS_FETCH_FAILURE] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.USER_INVITE_STATUS_FETCH_FAILURE] = state => + Object.assign({}, state, { inviteStatusIsPending: false, invitesRemaining: null, invitees: null, }); -}; export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; diff --git a/src/renderer/redux/reducers/wallet.js b/src/renderer/redux/reducers/wallet.js index 403c57486..bc5761c6c 100644 --- a/src/renderer/redux/reducers/wallet.js +++ b/src/renderer/redux/reducers/wallet.js @@ -18,13 +18,12 @@ const defaultState = { sendingSupport: false, }; -reducers[ACTIONS.FETCH_TRANSACTIONS_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.FETCH_TRANSACTIONS_STARTED] = state => + Object.assign({}, state, { fetchingTransactions: true, }); -}; -reducers[ACTIONS.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) { +reducers[ACTIONS.FETCH_TRANSACTIONS_COMPLETED] = (state, action) => { const byId = Object.assign({}, state.transactions); const { transactions } = action.data; @@ -39,13 +38,12 @@ reducers[ACTIONS.FETCH_TRANSACTIONS_COMPLETED] = function(state, action) { }); }; -reducers[ACTIONS.GET_NEW_ADDRESS_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.GET_NEW_ADDRESS_STARTED] = state => + Object.assign({}, state, { gettingNewAddress: true, }); -}; -reducers[ACTIONS.GET_NEW_ADDRESS_COMPLETED] = function(state, action) { +reducers[ACTIONS.GET_NEW_ADDRESS_COMPLETED] = (state, action) => { const { address } = action.data; localStorage.setItem('receiveAddress', address); @@ -55,25 +53,22 @@ reducers[ACTIONS.GET_NEW_ADDRESS_COMPLETED] = function(state, action) { }); }; -reducers[ACTIONS.UPDATE_BALANCE] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.UPDATE_BALANCE] = (state, action) => + Object.assign({}, state, { balance: action.data.balance, }); -}; -reducers[ACTIONS.CHECK_ADDRESS_IS_MINE_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.CHECK_ADDRESS_IS_MINE_STARTED] = state => + Object.assign({}, state, { checkingAddressOwnership: true, }); -}; -reducers[ACTIONS.CHECK_ADDRESS_IS_MINE_COMPLETED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.CHECK_ADDRESS_IS_MINE_COMPLETED] = state => + Object.assign({}, state, { checkingAddressOwnership: false, }); -}; -reducers[ACTIONS.SET_DRAFT_TRANSACTION_AMOUNT] = function(state, action) { +reducers[ACTIONS.SET_DRAFT_TRANSACTION_AMOUNT] = (state, action) => { const oldDraft = state.draftTransaction; const newDraft = Object.assign({}, oldDraft, { amount: parseFloat(action.data.amount), @@ -84,7 +79,7 @@ reducers[ACTIONS.SET_DRAFT_TRANSACTION_AMOUNT] = function(state, action) { }); }; -reducers[ACTIONS.SET_DRAFT_TRANSACTION_ADDRESS] = function(state, action) { +reducers[ACTIONS.SET_DRAFT_TRANSACTION_ADDRESS] = (state, action) => { const oldDraft = state.draftTransaction; const newDraft = Object.assign({}, oldDraft, { address: action.data.address, @@ -95,7 +90,7 @@ reducers[ACTIONS.SET_DRAFT_TRANSACTION_ADDRESS] = function(state, action) { }); }; -reducers[ACTIONS.SEND_TRANSACTION_STARTED] = function(state) { +reducers[ACTIONS.SEND_TRANSACTION_STARTED] = state => { const newDraftTransaction = Object.assign({}, state.draftTransaction, { sending: true, }); @@ -105,13 +100,12 @@ reducers[ACTIONS.SEND_TRANSACTION_STARTED] = function(state) { }); }; -reducers[ACTIONS.SEND_TRANSACTION_COMPLETED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.SEND_TRANSACTION_COMPLETED] = state => + Object.assign({}, state, { draftTransaction: buildDraftTransaction(), }); -}; -reducers[ACTIONS.SEND_TRANSACTION_FAILED] = function(state, action) { +reducers[ACTIONS.SEND_TRANSACTION_FAILED] = (state, action) => { const newDraftTransaction = Object.assign({}, state.draftTransaction, { sending: false, error: action.data.error, @@ -122,24 +116,21 @@ reducers[ACTIONS.SEND_TRANSACTION_FAILED] = function(state, action) { }); }; -reducers[ACTIONS.SUPPORT_TRANSACTION_STARTED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.SUPPORT_TRANSACTION_STARTED] = state => + Object.assign({}, state, { sendingSupport: true, }); -}; -reducers[ACTIONS.SUPPORT_TRANSACTION_COMPLETED] = function(state) { - return Object.assign({}, state, { +reducers[ACTIONS.SUPPORT_TRANSACTION_COMPLETED] = state => + Object.assign({}, state, { sendingSupport: false, }); -}; -reducers[ACTIONS.SUPPORT_TRANSACTION_FAILED] = function(state, action) { - return Object.assign({}, state, { +reducers[ACTIONS.SUPPORT_TRANSACTION_FAILED] = (state, action) => + Object.assign({}, state, { error: action.data.error, sendingSupport: false, }); -}; reducers[ACTIONS.FETCH_BLOCK_SUCCESS] = (state, action) => { const { block, block: { height } } = action.data; diff --git a/src/renderer/redux/selectors/app.js b/src/renderer/redux/selectors/app.js index 7a43f7fb3..052fe7096 100644 --- a/src/renderer/redux/selectors/app.js +++ b/src/renderer/redux/selectors/app.js @@ -58,8 +58,6 @@ export const selectUpgradeDownloadItem = createSelector(selectState, state => st export const selectModalProps = createSelector(selectState, state => state.modalProps); -export const selectDaemonReady = createSelector(selectState, state => state.daemonReady); - export const selectDaemonVersionMatched = createSelector( selectState, state => state.daemonVersionMatched diff --git a/src/renderer/redux/selectors/claims.js b/src/renderer/redux/selectors/claims.js index b0a62174a..4ee7faad8 100644 --- a/src/renderer/redux/selectors/claims.js +++ b/src/renderer/redux/selectors/claims.js @@ -1,6 +1,6 @@ -import { createSelector } from 'reselect'; import Lbryuri from 'lbryuri'; import { makeSelectCurrentParam } from 'redux/selectors/navigation'; +import { createSelector } from 'reselect'; const selectState = state => state.claims || {}; @@ -19,9 +19,7 @@ export const selectClaimsByUri = createSelector(selectState, selectClaimsById, ( if (claimId === null) { claims[uri] = null; } else { - const claim = byId[claimId]; - - claims[uri] = claim; + claims[uri] = byId[claimId]; } }); @@ -94,8 +92,7 @@ export const makeSelectMetadataForUri = uri => createSelector(makeSelectClaimForUri(uri), claim => { const metadata = claim && claim.value && claim.value.stream && claim.value.stream.metadata; - const value = metadata || (claim === undefined ? undefined : null); - return value; + return metadata || (claim === undefined ? undefined : null); }); export const makeSelectTitleForUri = uri => @@ -109,7 +106,7 @@ export const makeSelectContentTypeForUri = uri => export const selectIsFetchingClaimListMine = createSelector( selectState, - state => !!state.isFetchingClaimListMine + state => state.isFetchingClaimListMine ); export const selectPendingClaims = createSelector(selectState, state => @@ -154,7 +151,7 @@ export const selectMyClaimsOutpoints = createSelector(selectMyClaims, myClaims = export const selectFetchingMyChannels = createSelector( selectState, - state => !!state.fetchingMyChannels + state => state.fetchingMyChannels ); export const selectMyChannelClaims = createSelector( diff --git a/src/renderer/redux/selectors/content.js b/src/renderer/redux/selectors/content.js index 31e415dbe..371c59764 100644 --- a/src/renderer/redux/selectors/content.js +++ b/src/renderer/redux/selectors/content.js @@ -6,7 +6,7 @@ export const selectFeaturedUris = createSelector(selectState, state => state.fea export const selectFetchingFeaturedUris = createSelector( selectState, - state => !!state.fetchingFeaturedContent + state => state.fetchingFeaturedContent ); export const selectResolvingUris = createSelector(selectState, state => state.resolvingUris || []); diff --git a/src/renderer/redux/selectors/file_info.js b/src/renderer/redux/selectors/file_info.js index 9e2409911..f760bb3be 100644 --- a/src/renderer/redux/selectors/file_info.js +++ b/src/renderer/redux/selectors/file_info.js @@ -1,10 +1,9 @@ -import { createSelector } from 'reselect'; import { selectClaimsByUri, selectIsFetchingClaimListMine, selectMyClaims, - selectMyClaimsOutpoints, } from 'redux/selectors/claims'; +import { createSelector } from 'reselect'; export const selectState = state => state.fileInfo || {}; @@ -52,10 +51,6 @@ export const selectUrisLoading = createSelector(selectState, state => state.uris export const makeSelectLoadingForUri = uri => createSelector(selectUrisLoading, byUri => byUri && byUri[uri]); -export const selectFileInfosPendingPublish = createSelector(selectState, state => - Object.values(state.pendingByOutpoint || {}) -); - export const selectFileInfosDownloaded = createSelector( selectFileInfosByOutpoint, selectMyClaims, @@ -71,20 +66,6 @@ export const selectFileInfosDownloaded = createSelector( }) ); -export const selectFileInfosPublished = createSelector( - selectFileInfosByOutpoint, - selectMyClaimsOutpoints, - selectFileInfosPendingPublish, - (byOutpoint, outpoints, pendingPublish) => { - const fileInfos = []; - outpoints.forEach(outpoint => { - const fileInfo = byOutpoint[outpoint]; - if (fileInfo) fileInfos.push(fileInfo); - }); - return [...fileInfos, ...pendingPublish]; - } -); - // export const selectFileInfoForUri = (state, props) => { // const claims = selectClaimsByUri(state), // claim = claims[props.uri], @@ -94,26 +75,6 @@ export const selectFileInfosPublished = createSelector( // return outpoint && fileInfos ? fileInfos[outpoint] : undefined; // }; -export const selectFileInfosByUri = createSelector( - selectClaimsByUri, - selectFileInfosByOutpoint, - (claimsByUri, byOutpoint) => { - const fileInfos = {}; - const uris = Object.keys(claimsByUri); - - uris.forEach(uri => { - const claim = claimsByUri[uri]; - if (claim) { - const outpoint = `${claim.txid}:${claim.nout}`; - const fileInfo = byOutpoint[outpoint]; - - if (fileInfo) fileInfos[uri] = fileInfo; - } - }); - return fileInfos; - } -); - export const selectDownloadingFileInfos = createSelector( selectDownloadingByOutpoint, selectFileInfosByOutpoint, diff --git a/src/renderer/redux/selectors/search.js b/src/renderer/redux/selectors/search.js index b34a5742f..4e49f47d8 100644 --- a/src/renderer/redux/selectors/search.js +++ b/src/renderer/redux/selectors/search.js @@ -1,9 +1,9 @@ -import { createSelector } from 'reselect'; import { - selectPageTitle, selectCurrentPage, selectCurrentParams, + selectPageTitle, } from 'redux/selectors/navigation'; +import { createSelector } from 'reselect'; export const selectState = state => state.search || {}; @@ -13,7 +13,7 @@ export const selectSearchQuery = createSelector( (page, params) => (page === 'search' ? params && params.query : null) ); -export const selectIsSearching = createSelector(selectState, state => !!state.searching); +export const selectIsSearching = createSelector(selectState, state => state.searching); export const selectSearchUrisByQuery = createSelector(selectState, state => state.urisByQuery); diff --git a/src/renderer/redux/selectors/settings.js b/src/renderer/redux/selectors/settings.js index ba246f0cb..0e2887f59 100644 --- a/src/renderer/redux/selectors/settings.js +++ b/src/renderer/redux/selectors/settings.js @@ -13,11 +13,6 @@ export const selectClientSettings = createSelector( export const makeSelectClientSetting = setting => createSelector(selectClientSettings, settings => (settings ? settings[setting] : undefined)); -export const selectSettingsIsGenerous = createSelector( - selectDaemonSettings, - settings => settings && settings.is_generous_host -); - // refactor me export const selectShowNsfw = makeSelectClientSetting(SETTINGS.SHOW_NSFW); diff --git a/src/renderer/rewards.js b/src/renderer/rewards.js index d30ca1957..84dde2477 100644 --- a/src/renderer/rewards.js +++ b/src/renderer/rewards.js @@ -39,7 +39,7 @@ rewards.SORT_ORDER = [ rewards.TYPE_NEW_DEVELOPER, ]; -rewards.claimReward = function(type) { +rewards.claimReward = type => { function requestReward(resolve, reject, params) { if (!Lbryio.enabled) { reject(new Error(__('Rewards are not enabled.'))); diff --git a/src/renderer/util/setBadge.js b/src/renderer/util/setBadge.js index 005e63a11..ca4c9d358 100644 --- a/src/renderer/util/setBadge.js +++ b/src/renderer/util/setBadge.js @@ -1,4 +1,4 @@ -const { remote } = require('electron'); +import { remote } from 'electron'; const application = remote.app; const { dock } = application; diff --git a/src/renderer/util/shape_shift.js b/src/renderer/util/shape_shift.js index b61880e35..e958187a5 100644 --- a/src/renderer/util/shape_shift.js +++ b/src/renderer/util/shape_shift.js @@ -1,6 +1,6 @@ // these don't need to be exact -// shapeshift does a more thourough check on validity -// just general matches to prevent unneccesary api calls +// Shapeshift does a more thorough check on validity +// just general matches to prevent unnecessary api calls export const coinRegexPatterns = { BTC: /^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/, BCH: /^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/, diff --git a/src/renderer/util/throttle.js b/src/renderer/util/throttle.js index 941633deb..7b7c9b2b5 100644 --- a/src/renderer/util/throttle.js +++ b/src/renderer/util/throttle.js @@ -14,7 +14,7 @@ export default function throttle(func, wait, options = {}) { let previous = 0; const getNow = () => new Date().getTime(); - const later = function() { + const later = () => { previous = options.leading === false ? 0 : getNow(); timeout = null; result = func.apply(context, args); @@ -24,7 +24,7 @@ export default function throttle(func, wait, options = {}) { } }; - const throttled = function(...funcArgs) { + const throttled = function throttled(...funcArgs) { const now = getNow(); if (!previous && options.leading === false) previous = now; @@ -53,7 +53,7 @@ export default function throttle(func, wait, options = {}) { return result; }; - throttled.cancel = function() { + throttled.cancel = () => { clearTimeout(timeout); previous = 0; timeout = null; From e31e9cd345ee910bd6c609656c14d3c885ea46b3 Mon Sep 17 00:00:00 2001 From: Igor Gassmann Date: Wed, 27 Dec 2017 21:09:13 -0300 Subject: [PATCH 15/52] Change rule for func-names to as-needed --- .eslintrc.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 2fbd88746..2d095999a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,7 +1,5 @@ { - "plugins": [ - "flowtype" - ], + "plugins": ["flowtype"], "extends": [ "airbnb", "plugin:import/electron", @@ -28,7 +26,8 @@ "app": true }, "rules": { - "import/no-commonjs": 1, - "import/no-amd": 1 + "import/no-commonjs": "warn", + "import/no-amd": "warn", + "func-names": ["warn", "as-needed"] } -} \ No newline at end of file +} From b1a41892fb784f5e97545b69d9e39e6c39f512fe Mon Sep 17 00:00:00 2001 From: Igor Gassmann Date: Thu, 28 Dec 2017 11:18:20 -0300 Subject: [PATCH 16/52] Rename "pretty-print" command to "format" for more clarity --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 55b1a0905..7e94d5fe3 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "postinstall": "electron-builder install-app-deps", "precommit": "lint-staged", "lint": "eslint 'src/**/*.{js,jsx}' --fix", - "pretty-print": "prettier 'src/**/*.{js,jsx,scss,json}' --write" + "format": "prettier 'src/**/*.{js,jsx,scss,json}' --write" }, "keywords": [ "lbry" From c633c3c7cb50e2ad39ec4151bce9c198257553c0 Mon Sep 17 00:00:00 2001 From: Igor Gassmann Date: Thu, 28 Dec 2017 14:36:48 -0300 Subject: [PATCH 17/52] Update documentation for DevTools --- CONTRIBUTING.md | 162 ++++++++++++++++++++++++++++++++++++++---------- README.md | 96 +++++++++++++++++----------- 2 files changed, 190 insertions(+), 68 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f8c64645..29f49e38c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,57 +1,153 @@ -# Contributing to LBRY +# Contribute to LBRY -You found this page! That means you are well on your way to contributing to the LBRY app. This application is primarily written in JavaScript and is built on [Electron](https://electronjs.org) while utilizing [React](https://reactjs.org) and [Redux](https://redux.js.org) for UI and application state. +You found this page! That means you are well on your way to contributing to the LBRY app. This +application is primarily written in JavaScript and is built on [Electron](https://electronjs.org) +while utilizing [React](https://reactjs.org) and [Redux](https://redux.js.org) for UI and +application state. ## TL;DR? -* [Here](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+no%3Aassignee) is a list of help wanted issues. -* Comment on an issue to let us know if you are going to work on it, don't take an issue that someone has reserved less than 3 days ago + +* [Here](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+no%3Aassignee) + is a list of help wanted issues. +* Comment on an issue to let us know if you are going to work on it, don't take an issue that + someone reserved less than 3 days ago * Submit a pull request and get paid in LBC * Don't hesitate to contact us with any questions or comments -## Longer Version +## Choose an Issue -LBRY is an open source project, and therefore is developed out in the open for everyone to see. What you see here are the latest source code changes and issues. +LBRY is an open source project and therefore is developed out in the open for everyone to see. What +you see here are the latest source code changes and issues. -Since LBRY is an based around a decentralized community, we believe that the app will be strongest if it receives contributions from individuals outside the core team -- such as yourself! +Since LBRY is based on a decentralized community, we believe that the app will be stronger if it +receives contributions from individuals outside the core team -- such as yourself! -In order to make contributing as easy and rewarding of possible, we have instituted the following system: +To make contributing as easy and rewarding of possible, we have instituted the following system: -* Anyone can view all issues in the system by clicking on the [Issues](https://github.com/lbryio/lbry-app/issues) button at the top of the page. Feel free to add an issue if you think we have missed something (and you might earn some LBC in the process because we do tip people for reporting bugs). -* Once on the [Issues](https://github.com/lbryio/lbry-app/issues) page, a potential contributor can filter issues by the [Help Wanted](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+no%3Aassignee) label to see a curated list of suggested issues with which community members can help. -* Every [Help Wanted](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+no%3Aassignee) issue is ranked on a scale from zero to four. +* Anyone can view all issues in the system by clicking on the + [Issues](https://github.com/lbryio/lbry-app/issues) button at the top of the page. Feel free to + add an issue if you think we have missed something (and you might earn some LBC in the process + because we do tip people for reporting bugs). +* Once on the [Issues](https://github.com/lbryio/lbry-app/issues) page, a potential contributor can + filter issues by the + [Help Wanted](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+no%3Aassignee) + label to see a curated list of suggested issues with which community members can help. +* Every + [Help Wanted](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+no%3Aassignee) + issue is ranked on a scale from zero to four. -Level | Description ---- | --- -[**level 0**](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3A%22level+0%22+no%3Aassignee) | Typos and text edits -- a tech savvy non-programmer can fix these -[**level 1**](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3A%22level+1%22+no%3Aassignee) | Programming issues that require little knowledge of how the LBRY app works -[**level 2**](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3A%22level+2%22+no%3Aassignee) | Issues of average difficulty that require the developer to dig into how the app works a little bit -[**level 3**](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3A%22level+3%22+no%3Aassignee) | Issues that are likely too tricky to be level 2 or require more thinking outside of the box -[**level 4**](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3A%22level+4%22+no%3Aassignee) | Big features or really hard issues +| Level | Description | +| --------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| [**level 0**](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3A%22level+0%22+no%3Aassignee) | Typos and text edits -- a tech-savvy non-programmer can fix these | +| [**level 1**](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3A%22level+1%22+no%3Aassignee) | Programming issues that require little knowledge of how the LBRY app works | +| [**level 2**](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3A%22level+2%22+no%3Aassignee) | Issues of average difficulty that require the developer to dig into how the app works a little bit | +| [**level 3**](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3A%22level+3%22+no%3Aassignee) | Issues that are likely too tricky to be level 2 or require more thinking outside of the box | +| [**level 4**](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3A%22level+4%22+no%3Aassignee) | Big features or really hard issues | -The process of ranking issues is highly subjective. The purpose of sorting issues like this is to give contributors a general idea about the type of issues they are looking at. It could very well be the case that a level 1 issue is more difficult than a level 2, for instance. This system is meant to help you find relevant issues, not to prevent you from working on issues that you otherwise would. If these rankings don't work for you, feel free to ignore them. +The process of ranking issues is highly subjective. The purpose of sorting issues like this is to +give contributors a general idea about the type of issues they are looking at. It could very well be +the case that a level 1 issue is more difficult than a level 2, for instance. This system is meant +to help you find relevant issues, not to prevent you from working on issues that you otherwise +would. If these rankings don't work for you, feel free to ignore them. -* After deciding what to work on, a potential contributor can [fork](https://help.github.com/articles/fork-a-repo/) this repository, make his or her changes, and submit a [pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/). A contributor wanting to reserve an issue in advance can leave a comment saying that he or she is working on it. Contributors should respect other people's efforts to complete issues in a timely manner and, therefore, not begin working on anything reserved (or updated) within the last 3 days. If someone has been officially assigned an issue via Github's assignment system, it is also not available. Contributors are encouraged to ask if they have any questions about issue availability. -* Once the pull request is visible in the LBRY repo, a LBRY team member will review it and make sure it is up to our standards. At this point, the contributor may have to change his or her code based on our suggestions and comments. -* Then, upon a satisfactory review of the code, we will merge it and send the contributor a tip (in LBC) for the contribution. +## Develop -We are dedicated to being fair and friendly in this process. In __general__, level 4 issues will be paid more than level 3 issues which will be paid more than level 2, and so on. However, this is not due to their labeling, but rather how difficult they end up being. Maybe an issue labeled "level 1" turns out to be very difficult. In this case we would be **more than happy** to tip accordingly. If you do good work, we want you to be rewarded for it. +The project comes with diverse tools for simplifying the development process and for providing +better code quality. It's recommended to make use of them thoroughly during ongoing development. -Also, we are here to enable you. We want you to succeed, so do not hesitate to ask questions. If you need some information or assistance in completing an issue, please let us know! That is what we are here for-- pushing development forward. +We follow the well-known [Airbnb JavaScript Style Guide](http://airbnb.io/javascript/) for defining +our styling rules and code best practices. -Lastly, don't feel limited by this list. Should LBRY have built-in Tor support? Add it! It's not in the issue tracker but maybe it's a good idea. Do you think the search layout is unintuitive? Change it! We welcome all feedback and suggestions. That said, it may be the case that we do not wish to incorporate your change if you don't check with us first (also, please check with us especially if you are planning on adding Tor support :P). If you want to add a feature that is not listed in the issue tracker, go ahead and [create an issue](https://github.com/lbryio/lbry-app/issues/new), and say in the description that you would like to try to implement it yourself. This way we can tell you in advance if we will accept your changes and we can point you in the right direction. +### Run + +LBRY app can be run for development by using the command `yarn dev`. This will launch the app and +provide HMR (Hot Module Replacement). Any change made to the sources will automatically reload the +app without losing its state. + +### Lint + +Code linting is ensured by [ESLint](https://eslint.org/). + +You can lint all the project's sources at any time by using the `yarn lint` command. If you desire +to lint a specific file or directory you can use `yarn eslint 'glob/pattern'`. + +In addition to those commands, staged files are automatically linted before commit. Please take the +time to fix all staged files' linting problems before committing or suppress them if necessary. + +If you want the linting problems to show up on your IDE or text editor, check out +[ESLint integrations](https://eslint.org/docs/user-guide/integrations). + +### Code Formatting + +Project's sources are formatted using [Prettier](https://prettier.io/). + +Staged files are automatically formatted before commit. + +You can also use the command `yarn format` for applying formatting rules to all project's code +sources. For formatting a specific file or directory use `yarn prettier 'glob/pattern'`. + +Editor integrations are available [here](https://prettier.io/docs/en/editors.html). + +### Debug + +There are a few tools integrated to the project that will ease the process of debugging: + +* [Chrome DevTools](https://developer.chrome.com/devtools) + * Also available for the main process as a [remote target](chrome://inspect/#devices). +* [Electron Devtron](https://electronjs.org/devtron) +* [React DevTools](https://github.com/facebook/react-devtools) +* [Redux DevTools](https://github.com/gaearon/redux-devtools) + +## Submit a Pull Request + +* After deciding what to work on, a potential contributor can + [fork](https://help.github.com/articles/fork-a-repo/) this repository, make his or her changes, + and submit a + [pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/). A + contributor wanting to reserve an issue in advance can leave a comment saying that he or she is + working on it. Contributors should respect other people's efforts to complete issues in a timely + manner and, therefore, not begin working on anything reserved (or updated) within the last 3 days. + If someone has been officially assigned an issue via Github's assignment system, it is also not + available. Contributors are encouraged to ask if they have any questions about issue availability. +* Once the pull request is visible in the LBRY repo, a LBRY team member will review it and make sure + it is up to our standards. At this point, the contributor may have to change his or her code based + on our suggestions and comments. +* Then, upon a satisfactory review of the code, we will merge it and send the contributor a tip (in + LBC) for the contribution. + +We are dedicated to being fair and friendly in this process. In **general**, level 4 issues will be +paid more than level 3 issues which will be paid more than level 2, and so on. However, this is not +due to their labeling, but rather how difficult they end up being. Maybe an issue labeled "level 1" +turns out to be very difficult. In this case, we would be **more than happy** to tip accordingly. If +you do good work, we want you to be rewarded for it. + +Also, we are here to enable you. We want you to succeed, so do not hesitate to ask questions. If you +need some information or assistance in completing an issue, please let us know! That is what we are +here for-- pushing development forward. + +Lastly, don't feel limited by this list. Should LBRY have built-in Tor support? Add it! It's not in +the issue tracker, but maybe it's a good idea. Do you think the search layout is unintuitive? Change +it! We welcome all feedback and suggestions. That said, it may be the case that we do not wish to +incorporate your change if you don't check with us first (also, please check with us especially if +you are planning on adding Tor support :P). If you want to add a feature that is not listed in the +issue tracker, go ahead and [create an issue](https://github.com/lbryio/lbry-app/issues/new), and +say in the description that you would like to try to implement it yourself. This way we can tell you +in advance if we will accept your changes and we can point you in the right direction. # Tom's "Voice of the User" Wishlist -[Anything marked with **both** "Help Wanted" and "Tom's 'Voice of the User' Wishlist"](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22Tom%27s+%5C%22Voice+of+the+User%5C%22+Wishlist%22+label%3A%22help+wanted%22+no%3Aassignee) will earn you an extra 50 LBC on top of what we would otherwise tip you. +[Anything marked with **both** "Help Wanted" and "Tom's 'Voice of the User' Wishlist"](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22Tom%27s+%5C%22Voice+of+the+User%5C%22+Wishlist%22+label%3A%22help+wanted%22+no%3Aassignee) +will earn you an extra 50 LBC on top of what we would otherwise tip you. -# Get In Touch -Name | Role | Discord | Email ---- | --- | --- | --- -[Liam](https://github.com/liamcardenas) | The application engineer in charge of community development. He is the person to contact with any development/contribution related questions. | liamsdouble | liam@lbry.io -[Tom](https://github.com/tzarebczan) | Community manager. He knows more than anyone about the app and all of its flaws. Reach out to him with any questions about how the app works, if a bug has been reported, or if a feature should be requested. | jiggytom | tom@lbry.io -[Sean](https://github.com/seanyesmunt) | An application engineer who focuses largely on UI/UX. If you have a design or implementation question, feel free to reach out to him. | sean | sean@lbry.io +# Get in Touch -Join our discord [here](https://chat.lbry.io/). +| Name | Role | Discord | Email | +| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------------ | +| [Liam](https://github.com/liamcardenas) | The application engineer in charge of community development. He is the person to contact with any development/contribution related questions. | liamsdouble | liam@lbry.io | +| [Tom](https://github.com/tzarebczan) | Community manager. He knows more than anyone about the app and all of its flaws. Reach out to him with any questions about how the app works, if a bug has been reported, or if a feature should be requested. | jiggytom | tom@lbry.io | +| [Sean](https://github.com/seanyesmunt) | An application engineer who focuses largely on UI/UX. If you have a design or implementation question, feel free to reach out to him. | sean | sean@lbry.io | + +Join our Discord [here](https://chat.lbry.io/). # More Information diff --git a/README.md b/README.md index 9cb673480..a4544cd71 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,103 @@ # LBRY App -This is a graphical browser for the decentralized content marketplace provided by the [LBRY](https://lbry.io) protocol. It is essentially the [lbry daemon](https://github.com/lbryio/lbry) bundled with a UI using [Electron](http://electron.atom.io/). +The LBRY app is a graphical browser for the decentralized content marketplace provided by the +[LBRY](https://lbry.io) protocol. It is essentially the +[lbry daemon](https://github.com/lbryio/lbry) bundled with a UI using +[Electron](http://electron.atom.io/). -![App Screenshot](https://lbry.io/img/lbry-ui.png) +![App screenshot](https://lbry.io/img/lbry-ui.png) ## Installing We provide installers for Windows, macOS, and Debian-based Linux. -| | Windows | macOS | Linux | -| --- | --- | --- | --- | -| Latest Stable Release | [Download](https://lbry.io/get/lbry.exe) | [Download](https://lbry.io/get/lbry.dmg) | [Download](https://lbry.io/get/lbry.deb) | -| Latest Prerelease | [Download](https://lbry.io/get/lbry.pre.exe) | [Download](https://lbry.io/get/lbry.pre.dmg) | [Download](https://lbry.io/get/lbry.pre.deb) | +| | Windows | macOS | Linux | +| --------------------- | -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | +| Latest Stable Release | [Download](https://lbry.io/get/lbry.exe) | [Download](https://lbry.io/get/lbry.dmg) | [Download](https://lbry.io/get/lbry.deb) | +| Latest Prerelease | [Download](https://lbry.io/get/lbry.pre.exe) | [Download](https://lbry.io/get/lbry.pre.dmg) | [Download](https://lbry.io/get/lbry.pre.deb) | - -Our [releases page](https://github.com/lbryio/lbry-app/releases/latest) also contains the latest release, pre-releases, and past builds. +Our [releases page](https://github.com/lbryio/lbry-app/releases/latest) also contains the latest +release, pre-releases, and past builds. To install from source or make changes to the application, continue reading below. -## Development on Linux and macOS +## Getting Started + +These instructions will get you a copy of the project up and running on your local machine for +development and testing purposes. + +### Prerequisites + +* [Git](https://git-scm.com/downloads) +* [Node.js](https://nodejs.org/en/download/) +* [Yarn](https://yarnpkg.com/en/docs/install) +* `yarn --add-python-to-path install --global --production windows-build-tools` (Windows only) ### One-time Setup 1. Clone this repo 2. `DEPS=true ./build.sh` -This will download and install the LBRY app and its dependencies, including [the LBRY daemon](https://github.com/lbryio/lbry) and command line utilities like `node` and `yarn`. The LBRY app requires Node >= 6; if you have an earlier version of Node installed and want to keep it, you can use [nvm](https://github.com/creationix/nvm) to switch back and forth. +This will download and install the LBRY app and its dependencies, including +[the LBRY daemon](https://github.com/lbryio/lbry) and command line utilities like `node` and `yarn`. +The LBRY app requires Node >= 6; if you have an earlier version of Node installed and want to keep +it, you can use [nvm](https://github.com/creationix/nvm) to switch back and forth. -### Ongoing Development -Run `yarn dev` +### On Windows -This will set up a server that will automatically compile any changes made inside `src\` folder and automatically reload the app without losing the state. +#### Windows Dependency -### Build +1. Download and install `git` from github.io + (configure to use command prompt integration) +2. Download and install `npm` and `node` from + nodejs.org +3. Download and install `python 2.7` from + python.org +4. Download and Install `Microsoft Visual C++ Compiler for Python 2.7` from + Microsoft +5. Download and install `.NET Framework 2.0 Software Development Kit (SDK) (x64)` from + Microsoft (may need + to extract setup.exe and install manually by running install.exe as Administrator) -Run `yarn build` +#### One-time Setup -We use [electron-builder](https://github.com/electron-userland/electron-builder) -to create distributable packages. +1. Open a command prompt as administrator and run the following: -## Development on Windows - -### Windows Dependency -1. Download and install `git` from github.io (configure to use command prompt integration) -2. Download and install `npm` and `node` from nodejs.org -3. Download and install `python 2.7` from python.org -4. Download and Install `Microsoft Visual C++ Compiler for Python 2.7` from Microsoft -5. Download and install `.NET Framework 2.0 Software Development Kit (SDK) (x64)` from Microsoft (may need to extract setup.exe and install manually by running install.exe as Administrator) - -### One-time Setup -1. Open command prompt as adminstrator and run the following: ``` npm install --global --production windows-build-tools exit ``` -2. Open command prompt in the root of the project and run the following: +2. Open a command prompt in the root of the project and run the following: + ``` python -m pip install -r build\requirements.txt npm install -g yarn yarn install yarn build ``` -3. Download the lbry daemon and cli [binaries](https://github.com/lbryio/lbry/releases) and place them in `static\daemon` -### Ongoing Development -Run `yarn dev` +3. Download the lbry daemon and CLI [binaries](https://github.com/lbryio/lbry/releases) and place + them in `static\daemon`. ### Build -Run `yarn build` -This will set up a server that will automatically compile any changes made inside `src\` folder and automatically reload the app without losing the state. +Run `yarn build`. + +We use [electron-builder](https://github.com/electron-userland/electron-builder) to create +distributable packages. + +## Contributing + +Please read [our contributing manual](CONTRIBUTING.md) for details on how to develop for the +project and the process of submitting pull requests. ## Internationalization -If you want to help translating the lbry-app, you can copy the `en.json` file in `/dist/locales/` and modify the values while leaving the keys as their original English strings. An example for this would be: `"Skip": "Überspringen",` Translations should automatically show up in options. +If you want to help to translate the lbry-app, you can copy the `en.json` file in `/dist/locales/` +and modify the values while leaving the keys as their original English strings. An example for this +would be: `"Skip": "Überspringen",` Translations should automatically show up in options. + +## License + +[MIT © LBRY](LICENSE) From 1cf540986a34f35b7c4dd8f42c2681e29de00c30 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Thu, 28 Dec 2017 09:47:17 -0800 Subject: [PATCH 18/52] Added build instructions for arch linux and other distros --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 9cb673480..feb23d4bb 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,14 @@ To install from source or make changes to the application, continue reading belo This will download and install the LBRY app and its dependencies, including [the LBRY daemon](https://github.com/lbryio/lbry) and command line utilities like `node` and `yarn`. The LBRY app requires Node >= 6; if you have an earlier version of Node installed and want to keep it, you can use [nvm](https://github.com/creationix/nvm) to switch back and forth. +#### Arch Linux and Other Non-Debian Distributions + +Running the build script with `DEPS=true` triggers a bash script with `apt-get` specific commands. If you are using a distribution without `apt-get`, try running the script as: + +`./build.sh` + +You may also have to install the package [libsecret](https://wiki.gnome.org/Projects/Libsecret) if it is not already installed. + ### Ongoing Development Run `yarn dev` From c59293cf03b51c0db7e1710c96983343a016f592 Mon Sep 17 00:00:00 2001 From: Igor Gassmann Date: Thu, 28 Dec 2017 14:56:55 -0300 Subject: [PATCH 19/52] Fix default parameter for arrow functions --- src/renderer/lbry.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/renderer/lbry.js b/src/renderer/lbry.js index 0123f08c2..64ad8517e 100644 --- a/src/renderer/lbry.js +++ b/src/renderer/lbry.js @@ -19,7 +19,7 @@ const lbryProxy = new Proxy(Lbry, { return target[name]; } - return params => + return (params = {}) => new Promise((resolve, reject) => { apiCall(name, params, resolve, reject); }); @@ -213,7 +213,7 @@ Lbry.getAppVersionInfo = () => * Returns results from the file_list API method, plus dummy entries for pending publishes. * (If a real publish with the same name is found, the pending publish will be ignored and removed.) */ -Lbry.file_list = params => +Lbry.file_list = (params = {}) => new Promise((resolve, reject) => { const { name, channel_name: channelName, outpoint } = params; @@ -249,7 +249,7 @@ Lbry.file_list = params => ); }); -Lbry.claim_list_mine = params => +Lbry.claim_list_mine = (params = {}) => new Promise((resolve, reject) => { apiCall( 'claim_list_mine', @@ -270,7 +270,7 @@ Lbry.claim_list_mine = params => ); }); -Lbry.resolve = params => +Lbry.resolve = (params = {}) => new Promise((resolve, reject) => { apiCall( 'resolve', From a7aef67d68f88a694322bd3a24010765b6c6d6e7 Mon Sep 17 00:00:00 2001 From: Igor Gassmann Date: Thu, 28 Dec 2017 23:44:12 -0300 Subject: [PATCH 20/52] Add "Running" section --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index a4544cd71..8d84f9753 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,12 @@ This will download and install the LBRY app and its dependencies, including The LBRY app requires Node >= 6; if you have an earlier version of Node installed and want to keep it, you can use [nvm](https://github.com/creationix/nvm) to switch back and forth. +### Running + +The app can be run from the sources using the following command: + +`yarn dev` + ### On Windows #### Windows Dependency From 5d2a760b34e83489a2e68759c6e39c032d62ce23 Mon Sep 17 00:00:00 2001 From: Igor Gassmann Date: Thu, 28 Dec 2017 23:44:42 -0300 Subject: [PATCH 21/52] Put commands on its own line --- CONTRIBUTING.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 29f49e38c..3fcb763ec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,16 +60,22 @@ our styling rules and code best practices. ### Run -LBRY app can be run for development by using the command `yarn dev`. This will launch the app and -provide HMR (Hot Module Replacement). Any change made to the sources will automatically reload the -app without losing its state. +LBRY app can be run for development by using the command: + +`yarn dev` + +This will launch the app and provide HMR (Hot Module Replacement). Any change made to the sources +will automatically reload the app without losing its state. ### Lint Code linting is ensured by [ESLint](https://eslint.org/). -You can lint all the project's sources at any time by using the `yarn lint` command. If you desire -to lint a specific file or directory you can use `yarn eslint 'glob/pattern'`. +You can lint all the project's sources at any time by running: + +`yarn lint` + +If you desire to lint a specific file or directory you can use `yarn eslint 'glob/pattern'`. In addition to those commands, staged files are automatically linted before commit. Please take the time to fix all staged files' linting problems before committing or suppress them if necessary. @@ -83,8 +89,12 @@ Project's sources are formatted using [Prettier](https://prettier.io/). Staged files are automatically formatted before commit. -You can also use the command `yarn format` for applying formatting rules to all project's code -sources. For formatting a specific file or directory use `yarn prettier 'glob/pattern'`. +You can also use the following command: + +`yarn format` + +for applying formatting rules to all project's code sources. For formatting a specific file or +directory use `yarn prettier 'glob/pattern'`. Editor integrations are available [here](https://prettier.io/docs/en/editors.html). From a8988d9e0504a1ddc2a8c1aa835f5bae017e9aea Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Fri, 29 Dec 2017 11:07:03 -0500 Subject: [PATCH 22/52] remove video files; save video claimId rather than URI --- src/renderer/component/video/index.js | 6 ++--- .../component/video/internal/player.jsx | 6 +++-- src/renderer/component/video/view.jsx | 8 +++--- src/renderer/redux/actions/video.js | 10 -------- src/renderer/redux/reducers/media.js | 4 ++- src/renderer/redux/reducers/video.js | 25 ------------------- src/renderer/redux/selectors/media.js | 12 +++++++-- src/renderer/redux/selectors/video.js | 9 ------- src/renderer/store.js | 2 -- 9 files changed, 23 insertions(+), 59 deletions(-) delete mode 100644 src/renderer/redux/actions/video.js delete mode 100644 src/renderer/redux/reducers/video.js delete mode 100644 src/renderer/redux/selectors/video.js diff --git a/src/renderer/component/video/index.js b/src/renderer/component/video/index.js index 36c92eab9..cc01f032a 100644 --- a/src/renderer/component/video/index.js +++ b/src/renderer/component/video/index.js @@ -4,7 +4,6 @@ import { doChangeVolume } from "redux/actions/app"; import { selectVolume } from "redux/selectors/app"; import { doPlayUri, doSetPlayingUri } from "redux/actions/content"; import { doPlay, doPause, savePosition } from "redux/actions/media"; -// import { setVideoPause } from "redux/actions/video"; import { makeSelectMetadataForUri, makeSelectContentTypeForUri, @@ -16,15 +15,16 @@ import { } from "redux/selectors/file_info"; import { makeSelectCostInfoForUri } from "redux/selectors/cost_info"; import { selectShowNsfw } from "redux/selectors/settings"; -// import { selectVideoPause } from "redux/selectors/video"; import { selectMediaPaused, makeSelectMediaPositionForUri, } from "redux/selectors/media"; import Video from "./view"; import { selectPlayingUri } from "redux/selectors/content"; +import { makeSelectClaimForUri } from "redux/selectors/claims"; const select = (state, props) => ({ + claim: makeSelectClaimForUri(props.uri)(state), costInfo: makeSelectCostInfoForUri(props.uri)(state), fileInfo: makeSelectFileInfoForUri(props.uri)(state), metadata: makeSelectMetadataForUri(props.uri)(state), @@ -34,7 +34,6 @@ const select = (state, props) => ({ playingUri: selectPlayingUri(state), contentType: makeSelectContentTypeForUri(props.uri)(state), volume: selectVolume(state), - // videoPause: selectVideoPause(state), mediaPaused: selectMediaPaused(state), mediaPosition: makeSelectMediaPositionForUri(props.uri)(state), }); @@ -43,7 +42,6 @@ const perform = dispatch => ({ play: uri => dispatch(doPlayUri(uri)), cancelPlay: () => dispatch(doSetPlayingUri(null)), changeVolume: volume => dispatch(doChangeVolume(volume)), - // setVideoPause: val => dispatch(setVideoPause(val)), doPlay: () => dispatch(doPlay()), doPause: () => dispatch(doPause()), savePosition: (id, position) => dispatch(savePosition(id, position)), diff --git a/src/renderer/component/video/internal/player.jsx b/src/renderer/component/video/internal/player.jsx index 3d675c723..2e9a9a0b1 100644 --- a/src/renderer/component/video/internal/player.jsx +++ b/src/renderer/component/video/internal/player.jsx @@ -34,10 +34,12 @@ class VideoPlayer extends React.PureComponent { mediaType, changeVolume, volume, - mediaId, position, + id, } = this.props; + console.log("position:", position); + const loadedMetadata = e => { this.setState({ hasMetadata: true, startedPlaying: true }); this.refs.media.children[0].play(); @@ -74,7 +76,7 @@ class VideoPlayer extends React.PureComponent { mediaElement.addEventListener("play", () => this.props.doPlay()); mediaElement.addEventListener("pause", () => this.props.doPause()); mediaElement.addEventListener("timeupdate", () => - this.props.savePosition(mediaId, mediaElement.currentTime) + this.props.savePosition(id, mediaElement.currentTime) ); mediaElement.addEventListener("click", this.togglePlayListener); mediaElement.addEventListener( diff --git a/src/renderer/component/video/view.jsx b/src/renderer/component/video/view.jsx index 96715c990..77b7463ab 100644 --- a/src/renderer/component/video/view.jsx +++ b/src/renderer/component/video/view.jsx @@ -55,6 +55,7 @@ class Video extends React.PureComponent { contentType, changeVolume, volume, + claim, uri, doPlay, doPause, @@ -63,6 +64,8 @@ class Video extends React.PureComponent { mediaPosition, } = this.props; + console.log("mediaPosition:", mediaPosition); + const isPlaying = playingUri === uri; const isReadyToPlay = fileInfo && fileInfo.written_bytes > 0; const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw; @@ -96,9 +99,6 @@ class Video extends React.PureComponent { } const poster = metadata.thumbnail; - const mediaId = uri.split("#")[1]; - console.log("mediaId:", mediaId); - return (
diff --git a/src/renderer/redux/actions/video.js b/src/renderer/redux/actions/video.js deleted file mode 100644 index bf88d2d26..000000000 --- a/src/renderer/redux/actions/video.js +++ /dev/null @@ -1,10 +0,0 @@ -// @flow -import * as actions from "constants/action_types"; -import type { Action, Dispatch } from "redux/reducers/video"; -import lbry from "lbry"; - -export const setVideoPause = (data: boolean) => (dispatch: Dispatch) => - dispatch({ - type: actions.SET_VIDEO_PAUSE, - data, - }); diff --git a/src/renderer/redux/reducers/media.js b/src/renderer/redux/reducers/media.js index 242f65be7..92d5f4115 100644 --- a/src/renderer/redux/reducers/media.js +++ b/src/renderer/redux/reducers/media.js @@ -4,7 +4,9 @@ import { handleActions } from "util/redux-utils"; export type MediaState = { paused: Boolean, - positions: Object, + positions: { + [string]: number, + }, }; export type Action = any; diff --git a/src/renderer/redux/reducers/video.js b/src/renderer/redux/reducers/video.js deleted file mode 100644 index 0f18844dd..000000000 --- a/src/renderer/redux/reducers/video.js +++ /dev/null @@ -1,25 +0,0 @@ -// @flow -import * as actions from "constants/action_types"; -import { handleActions } from "util/redux-utils"; - -export type VideoState = { videoPause: boolean }; - -type setVideoPause = { - type: actions.SET_VIDEO_PAUSE, - data: boolean, -}; - -export type Action = setVideoPause; -export type Dispatch = (action: Action) => any; - -const defaultState = { videoPause: false }; - -export default handleActions( - { - [actions.SET_VIDEO_PAUSE]: ( - state: VideoState, - action: setVideoPause - ): VideoState => ({ ...state, videoPause: action.data }), - }, - defaultState -); diff --git a/src/renderer/redux/selectors/media.js b/src/renderer/redux/selectors/media.js index 070604c2b..f0cf17886 100644 --- a/src/renderer/redux/selectors/media.js +++ b/src/renderer/redux/selectors/media.js @@ -1,5 +1,6 @@ import * as settings from "constants/settings"; import { createSelector } from "reselect"; +import lbryuri from "lbryuri"; const _selectState = state => state.media || {}; @@ -10,6 +11,13 @@ export const selectMediaPaused = createSelector( export const makeSelectMediaPositionForUri = uri => createSelector(_selectState, state => { - const id = uri.split("#")[1]; - return state.positions[id] || null; + // console.log("select positions:", state.positions); + // const videoId = lbryuri.parse(uri).claimId; + // console.log("videoId:", videoId); + // const position = state.positions[videoId]; + // console.log("position:", position); + // console.log("positions:", state.positions); + const obj = lbryuri.parse(uri); + console.log("state.positions:\n", state.positions); + return state.positions[obj.claimId] || null; }); diff --git a/src/renderer/redux/selectors/video.js b/src/renderer/redux/selectors/video.js deleted file mode 100644 index a41c95803..000000000 --- a/src/renderer/redux/selectors/video.js +++ /dev/null @@ -1,9 +0,0 @@ -import * as settings from "constants/settings"; -import { createSelector } from "reselect"; - -const _selectState = state => state.video || {}; - -export const selectVideoPause = createSelector( - _selectState, - state => state.videoPause -); diff --git a/src/renderer/store.js b/src/renderer/store.js index 8c6e89277..836412983 100644 --- a/src/renderer/store.js +++ b/src/renderer/store.js @@ -13,7 +13,6 @@ import userReducer from "redux/reducers/user"; import walletReducer from "redux/reducers/wallet"; import shapeShiftReducer from "redux/reducers/shape_shift"; import subscriptionsReducer from "redux/reducers/subscriptions"; -import videoReducer from "redux/reducers/video"; import mediaReducer from "redux/reducers/media"; import { persistStore, autoRehydrate } from "redux-persist"; import createCompressor from "redux-persist-transform-compress"; @@ -71,7 +70,6 @@ const reducers = combineReducers({ user: userReducer, shapeShift: shapeShiftReducer, subscriptions: subscriptionsReducer, - video: videoReducer, media: mediaReducer, }); From bfe5fe851aa972a73f0faa38f8ab5ae17e5bff5c Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Fri, 29 Dec 2017 15:45:32 -0500 Subject: [PATCH 23/52] remove logging --- src/renderer/component/video/internal/player.jsx | 2 -- src/renderer/redux/selectors/media.js | 7 ------- 2 files changed, 9 deletions(-) diff --git a/src/renderer/component/video/internal/player.jsx b/src/renderer/component/video/internal/player.jsx index 2e9a9a0b1..fdb5dccc3 100644 --- a/src/renderer/component/video/internal/player.jsx +++ b/src/renderer/component/video/internal/player.jsx @@ -38,8 +38,6 @@ class VideoPlayer extends React.PureComponent { id, } = this.props; - console.log("position:", position); - const loadedMetadata = e => { this.setState({ hasMetadata: true, startedPlaying: true }); this.refs.media.children[0].play(); diff --git a/src/renderer/redux/selectors/media.js b/src/renderer/redux/selectors/media.js index f0cf17886..a3418775d 100644 --- a/src/renderer/redux/selectors/media.js +++ b/src/renderer/redux/selectors/media.js @@ -11,13 +11,6 @@ export const selectMediaPaused = createSelector( export const makeSelectMediaPositionForUri = uri => createSelector(_selectState, state => { - // console.log("select positions:", state.positions); - // const videoId = lbryuri.parse(uri).claimId; - // console.log("videoId:", videoId); - // const position = state.positions[videoId]; - // console.log("position:", position); - // console.log("positions:", state.positions); const obj = lbryuri.parse(uri); - console.log("state.positions:\n", state.positions); return state.positions[obj.claimId] || null; }); From ecd2207314d6067b3f08fbcfad8fd96c3d6d4c05 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Fri, 29 Dec 2017 15:47:11 -0500 Subject: [PATCH 24/52] remove log in video view --- src/renderer/component/video/view.jsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/renderer/component/video/view.jsx b/src/renderer/component/video/view.jsx index 77b7463ab..1daf4e00e 100644 --- a/src/renderer/component/video/view.jsx +++ b/src/renderer/component/video/view.jsx @@ -64,8 +64,6 @@ class Video extends React.PureComponent { mediaPosition, } = this.props; - console.log("mediaPosition:", mediaPosition); - const isPlaying = playingUri === uri; const isReadyToPlay = fileInfo && fileInfo.written_bytes > 0; const obscureNsfw = this.props.obscureNsfw && metadata && metadata.nsfw; From a5dc55241c8a915642bbf2e7d1f1e53740a2f150 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 29 Dec 2017 15:43:51 -0800 Subject: [PATCH 25/52] Removed email verification reward messaging --- src/renderer/component/userEmailNew/index.js | 5 ----- src/renderer/component/userEmailNew/view.jsx | 11 ++--------- src/renderer/component/userEmailVerify/index.js | 5 ----- src/renderer/component/userEmailVerify/view.jsx | 3 +-- 4 files changed, 3 insertions(+), 21 deletions(-) diff --git a/src/renderer/component/userEmailNew/index.js b/src/renderer/component/userEmailNew/index.js index 98cc7bd04..0228a4aaa 100644 --- a/src/renderer/component/userEmailNew/index.js +++ b/src/renderer/component/userEmailNew/index.js @@ -3,15 +3,10 @@ import { connect } from 'react-redux'; import { doUserEmailNew, doUserInviteNew } from 'redux/actions/user'; import { selectEmailNewIsPending, selectEmailNewErrorMessage } from 'redux/selectors/user'; import UserEmailNew from './view'; -import rewards from 'rewards'; -import { makeSelectRewardAmountByType } from 'redux/selectors/rewards'; const select = state => ({ isPending: selectEmailNewIsPending(state), errorMessage: selectEmailNewErrorMessage(state), - rewardAmount: makeSelectRewardAmountByType()(state, { - reward_type: rewards.TYPE_CONFIRM_EMAIL, - }), }); const perform = dispatch => ({ diff --git a/src/renderer/component/userEmailNew/view.jsx b/src/renderer/component/userEmailNew/view.jsx index 05e9a1e2d..661adb611 100644 --- a/src/renderer/component/userEmailNew/view.jsx +++ b/src/renderer/component/userEmailNew/view.jsx @@ -1,5 +1,4 @@ import React from 'react'; -import { CreditAmount } from 'component/common'; import { Form, FormRow, Submit } from 'component/form.js'; class UserEmailNew extends React.PureComponent { @@ -23,18 +22,12 @@ class UserEmailNew extends React.PureComponent { } render() { - const { cancelButton, errorMessage, isPending, rewardAmount } = this.props; + const { cancelButton, errorMessage, isPending } = this.props; return (

- Let us know your email and you'll receive{' '} - , the blockchain token used by LBRY. -

-

- {__( - "We'll also let you know about LBRY updates, security issues, and great new content." - )} + {__("We'll let you know about LBRY updates, security issues, and great new content.")}

{__("We'll never sell your email, and you can unsubscribe at any time.")}

diff --git a/src/renderer/component/userEmailVerify/index.js b/src/renderer/component/userEmailVerify/index.js index 9a10f7785..f8c854ca1 100644 --- a/src/renderer/component/userEmailVerify/index.js +++ b/src/renderer/component/userEmailVerify/index.js @@ -7,16 +7,11 @@ import { selectEmailVerifyErrorMessage, } from 'redux/selectors/user'; import UserEmailVerify from './view'; -import rewards from 'rewards'; -import { makeSelectRewardAmountByType } from 'redux/selectors/rewards'; const select = state => ({ isPending: selectEmailVerifyIsPending(state), email: selectEmailToVerify(state), errorMessage: selectEmailVerifyErrorMessage(state), - rewardAmount: makeSelectRewardAmountByType()(state, { - reward_type: rewards.TYPE_CONFIRM_EMAIL, - }), }); const perform = dispatch => ({ diff --git a/src/renderer/component/userEmailVerify/view.jsx b/src/renderer/component/userEmailVerify/view.jsx index 149b68d17..3304730b9 100644 --- a/src/renderer/component/userEmailVerify/view.jsx +++ b/src/renderer/component/userEmailVerify/view.jsx @@ -1,6 +1,5 @@ import React from 'react'; import Link from 'component/link'; -import { CreditAmount } from 'component/common'; import { Form, FormRow, Submit } from 'component/form.js'; class UserEmailVerify extends React.PureComponent { @@ -29,7 +28,7 @@ class UserEmailVerify extends React.PureComponent { } render() { - const { cancelButton, errorMessage, email, isPending, rewardAmount } = this.props; + const { cancelButton, errorMessage, email, isPending } = this.props; return (

Please enter the verification code emailed to {email}.

From 5a5dcb15c0d72101f43262f69237579554be8378 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 29 Dec 2017 16:23:46 -0800 Subject: [PATCH 26/52] Fixed error caused by using deprecated selector --- src/renderer/modal/modalCreditIntro/index.js | 22 ++++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/renderer/modal/modalCreditIntro/index.js b/src/renderer/modal/modalCreditIntro/index.js index a6eb79720..247d2ff5d 100644 --- a/src/renderer/modal/modalCreditIntro/index.js +++ b/src/renderer/modal/modalCreditIntro/index.js @@ -1,28 +1,18 @@ -import React from 'react'; import { connect } from 'react-redux'; import { doCloseModal } from 'redux/actions/app'; import { doNavigate } from 'redux/actions/navigation'; import { doSetClientSetting } from 'redux/actions/settings'; import { selectUserIsRewardApproved } from 'redux/selectors/user'; import { selectBalance } from 'redux/selectors/wallet'; -import { - makeSelectHasClaimedReward, - makeSelectRewardByType, - selectUnclaimedRewardValue, -} from 'redux/selectors/rewards'; +import { selectUnclaimedRewardValue } from 'redux/selectors/rewards'; import * as settings from 'constants/settings'; import ModalCreditIntro from './view'; -const select = (state, props) => { - const selectHasClaimed = makeSelectHasClaimedReward(), - selectReward = makeSelectRewardByType(); - - return { - currentBalance: selectBalance(state), - isRewardApproved: selectUserIsRewardApproved(state), - totalRewardValue: selectUnclaimedRewardValue(state), - }; -}; +const select = state => ({ + currentBalance: selectBalance(state), + isRewardApproved: selectUserIsRewardApproved(state), + totalRewardValue: selectUnclaimedRewardValue(state), +}); const perform = dispatch => () => ({ addBalance: () => { From cb26a92cde9a559412c8c30807c49f1fdbdd6d03 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 29 Dec 2017 16:57:07 -0800 Subject: [PATCH 27/52] Update CHANGELOG.md --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0da8b5c7..d2c2c512b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,11 +12,12 @@ Web UI version numbers should always match the corresponding version of LBRY App * ### Changed - * + * Improved internal code structuring by adding linting integration -- developers only (#891) + * Improved developer documentation (#910) * ### Fixed - * + * Added snackbar text in place where it was coming up blank (#902) * ### Deprecated @@ -24,7 +25,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * ### Removed - * + * Removed email verification reward (#914) * ## [0.19.2] - 2017-12-22 From 4a904ef374026546acbce16e5e03f69b09db90f8 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 29 Dec 2017 17:07:43 -0800 Subject: [PATCH 28/52] =?UTF-8?q?Bump=20version:=200.19.2=20=E2=86=92=200.?= =?UTF-8?q?19.3rc1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index dd3d60359..28099a6df 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.2 +current_version = 0.19.3rc1 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/package.json b/package.json index 55b1a0905..9cbfc71e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.2", + "version": "0.19.3rc1", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": { From 410996aa818661f940a011f23fcefb29da3e6b69 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Sat, 30 Dec 2017 12:59:37 -0800 Subject: [PATCH 29/52] Disabled dependence on confirm email reward --- src/renderer/modal/modalFirstReward/index.js | 2 +- src/renderer/redux/actions/rewards.js | 2 +- src/renderer/redux/actions/user.js | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/renderer/modal/modalFirstReward/index.js b/src/renderer/modal/modalFirstReward/index.js index eb9f65297..77d8ac376 100644 --- a/src/renderer/modal/modalFirstReward/index.js +++ b/src/renderer/modal/modalFirstReward/index.js @@ -9,7 +9,7 @@ const select = (state, props) => { const selectReward = makeSelectRewardByType(); return { - reward: selectReward(state, { reward_type: rewards.TYPE_CONFIRM_EMAIL }), + reward: selectReward(state, { reward_type: rewards.TYPE_NEW_USER }), }; }; diff --git a/src/renderer/redux/actions/rewards.js b/src/renderer/redux/actions/rewards.js index 4c4a278cd..456577e0a 100644 --- a/src/renderer/redux/actions/rewards.js +++ b/src/renderer/redux/actions/rewards.js @@ -60,7 +60,7 @@ export function doClaimRewardType(rewardType) { reward: successReward, }, }); - if (successReward.reward_type === rewards.TYPE_CONFIRM_EMAIL) { + if (successReward.reward_type === rewards.TYPE_NEW_USER) { dispatch({ type: ACTIONS.OPEN_MODAL, data: { modal: MODALS.FIRST_REWARD }, diff --git a/src/renderer/redux/actions/user.js b/src/renderer/redux/actions/user.js index 32d9fafc8..faaa4a639 100644 --- a/src/renderer/redux/actions/user.js +++ b/src/renderer/redux/actions/user.js @@ -149,7 +149,6 @@ export function doUserEmailVerify(verificationToken, recaptcha) { type: ACTIONS.USER_EMAIL_VERIFY_SUCCESS, data: { email }, }); - dispatch(doClaimRewardType(rewards.TYPE_CONFIRM_EMAIL)); dispatch(doUserFetch()); } else { throw new Error('Your email is still not verified.'); // shouldn't happen From 722a25b477543984319d2579df966f31adb8c54c Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Sat, 30 Dec 2017 13:09:17 -0800 Subject: [PATCH 30/52] =?UTF-8?q?Bump=20version:=200.19.3rc1=20=E2=86=92?= =?UTF-8?q?=200.19.3rc2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 28099a6df..470c3a57f 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.3rc1 +current_version = 0.19.3rc2 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/package.json b/package.json index 9cbfc71e3..187a36f54 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.3rc1", + "version": "0.19.3rc2", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": { From f750fd399d09625c50fad985cb920fc9284b60a5 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Sat, 30 Dec 2017 14:24:36 -0800 Subject: [PATCH 31/52] =?UTF-8?q?Bump=20version:=200.19.3rc2=20=E2=86=92?= =?UTF-8?q?=200.19.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CHANGELOG.md | 23 +++++++++++++++++++---- package.json | 2 +- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 470c3a57f..0e0eb1a42 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.3rc2 +current_version = 0.19.3 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/CHANGELOG.md b/CHANGELOG.md index d2c2c512b..5909b74bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,12 +12,11 @@ Web UI version numbers should always match the corresponding version of LBRY App * ### Changed - * Improved internal code structuring by adding linting integration -- developers only (#891) - * Improved developer documentation (#910) + * * ### Fixed - * Added snackbar text in place where it was coming up blank (#902) + * * ### Deprecated @@ -25,8 +24,24 @@ Web UI version numbers should always match the corresponding version of LBRY App * ### Removed - * Removed email verification reward (#914) * + * + +## [0.19.3] - 2017-12-30 + +### Changed + * Improved internal code structuring by adding linting integration -- developers only (#891) + * Improved developer documentation (#910) + + +### Removed + * Removed email verification reward (#914) + + +### Fixed + * Added snackbar text in place where it was coming up blank (#902) + + ## [0.19.2] - 2017-12-22 diff --git a/package.json b/package.json index 187a36f54..5926ef727 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.3rc2", + "version": "0.19.3", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": { From 4e97c105c47d8f6d40bebaf3648c6549ff059f2b Mon Sep 17 00:00:00 2001 From: Igor Gassmann Date: Tue, 2 Jan 2018 09:07:28 -0300 Subject: [PATCH 32/52] Fix cannot send tip, transaction failed (#917) --- src/renderer/redux/actions/wallet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/redux/actions/wallet.js b/src/renderer/redux/actions/wallet.js index 9976c98ff..df2faeb8d 100644 --- a/src/renderer/redux/actions/wallet.js +++ b/src/renderer/redux/actions/wallet.js @@ -200,7 +200,7 @@ export function doSendSupport(amount, claimId, uri) { }; Lbry.wallet_send({ - claimId, + claim_id: claimId, amount, }).then(successCallback, errorCallback); }; From 0e77be0ab5b73df4010365f5d9bbdd485a1b0c8c Mon Sep 17 00:00:00 2001 From: Igor Gassmann Date: Tue, 2 Jan 2018 16:54:57 -0300 Subject: [PATCH 33/52] HOTFIX: Fix creation of channel --- src/renderer/redux/actions/content.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/renderer/redux/actions/content.js b/src/renderer/redux/actions/content.js index 7ed21e4f1..a5df999ed 100644 --- a/src/renderer/redux/actions/content.js +++ b/src/renderer/redux/actions/content.js @@ -279,9 +279,7 @@ export function doLoadVideo(uri) { }); dispatch( doAlertError( - `Failed to download ${ - uri - }, please try again. If this problem persists, visit https://lbry.io/faq/support for support.` + `Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.io/faq/support for support.` ) ); }); @@ -444,14 +442,14 @@ export function doCreateChannel(name, amount) { channel_name: name, amount: parseFloat(amount), }).then( - channelClaim => { - const newChannelClaim = channelClaim; - newChannelClaim.name = name; + newChannelClaim => { + const channelClaim = newChannelClaim; + channelClaim.name = name; dispatch({ type: ACTIONS.CREATE_CHANNEL_COMPLETED, - data: { newChannelClaim }, + data: { channelClaim }, }); - resolve(newChannelClaim); + resolve(channelClaim); }, error => { reject(error); From 6ec7b81409839556916d696813bdc8496f7ab266 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Tue, 2 Jan 2018 15:04:14 -0800 Subject: [PATCH 34/52] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3fcb763ec..8e10e6644 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,6 +50,8 @@ the case that a level 1 issue is more difficult than a level 2, for instance. Th to help you find relevant issues, not to prevent you from working on issues that you otherwise would. If these rankings don't work for you, feel free to ignore them. +The (UX label, when applied in conjunction with Help Wanted)[https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Aux], indicates that the contributor ought to implement the feature in a creative way that provides a good user experience. These issues often have no set instruction for how the experience should be and leave it to the contributor to figure out. This may be challenging for people who do not like UX, but also more fun and rewarding for those who do. + ## Develop The project comes with diverse tools for simplifying the development process and for providing From f4c894deef8b371851789e5e978299a17428f1a0 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Tue, 2 Jan 2018 15:05:15 -0800 Subject: [PATCH 35/52] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8e10e6644..4117f0aac 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,7 +50,7 @@ the case that a level 1 issue is more difficult than a level 2, for instance. Th to help you find relevant issues, not to prevent you from working on issues that you otherwise would. If these rankings don't work for you, feel free to ignore them. -The (UX label, when applied in conjunction with Help Wanted)[https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Aux], indicates that the contributor ought to implement the feature in a creative way that provides a good user experience. These issues often have no set instruction for how the experience should be and leave it to the contributor to figure out. This may be challenging for people who do not like UX, but also more fun and rewarding for those who do. +The [UX label, when applied in conjunction with Help Wanted](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Aux), indicates that the contributor ought to implement the feature in a creative way that provides a good user experience. These issues often have no set instruction for how the experience should be and leave it to the contributor to figure out. This may be challenging for people who do not like UX, but also more fun and rewarding for those who do. ## Develop From 77b06067514d9a7e7147fac12880b8a78ae2dc7b Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Tue, 2 Jan 2018 15:07:48 -0800 Subject: [PATCH 36/52] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4117f0aac..8390e89a2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,7 +50,7 @@ the case that a level 1 issue is more difficult than a level 2, for instance. Th to help you find relevant issues, not to prevent you from working on issues that you otherwise would. If these rankings don't work for you, feel free to ignore them. -The [UX label, when applied in conjunction with Help Wanted](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Aux), indicates that the contributor ought to implement the feature in a creative way that provides a good user experience. These issues often have no set instruction for how the experience should be and leave it to the contributor to figure out. This may be challenging for people who do not like UX, but also more fun and rewarding for those who do. +The [UX label, when applied in conjunction with Help Wanted](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Aux+no%3Aassignee), indicates that the contributor ought to implement the feature in a creative way that provides a good user experience. These issues often have no set instruction for how the experience should be and leave it to the contributor to figure out. This may be challenging for people who do not like UX, but also more fun and rewarding for those who do. ## Develop From d4f67ec521adc2d096ad4c55956a1bc451a71830 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Tue, 2 Jan 2018 15:15:30 -0800 Subject: [PATCH 37/52] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8390e89a2..578abc5f7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,7 +50,7 @@ the case that a level 1 issue is more difficult than a level 2, for instance. Th to help you find relevant issues, not to prevent you from working on issues that you otherwise would. If these rankings don't work for you, feel free to ignore them. -The [UX label, when applied in conjunction with Help Wanted](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Aux+no%3Aassignee), indicates that the contributor ought to implement the feature in a creative way that provides a good user experience. These issues often have no set instruction for how the experience should be and leave it to the contributor to figure out. This may be challenging for people who do not like UX, but also more fun and rewarding for those who do. +Although all contributions should have good UX, the [UX label, when applied in conjunction with Help Wanted](https://github.com/lbryio/lbry-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Aux+no%3Aassignee), indicates that the contributor ought to implement the feature in a creative way that specifically focuses on providing a good user experience. These issues often have no set instruction for how the experience should be and leave it to the contributor to figure out. This may be challenging for people who do not like UX, but also more fun and rewarding for those who do. ## Develop From 535730eede2d2f64961f46e262fdc880158e91c9 Mon Sep 17 00:00:00 2001 From: Thomas Zarebczan Date: Tue, 2 Jan 2018 19:47:48 -0500 Subject: [PATCH 38/52] update wunderbar text change "movies" to "videos" (more generic) --- src/renderer/component/wunderbar/view.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/component/wunderbar/view.jsx b/src/renderer/component/wunderbar/view.jsx index b0242baff..9c3725bed 100644 --- a/src/renderer/component/wunderbar/view.jsx +++ b/src/renderer/component/wunderbar/view.jsx @@ -160,7 +160,7 @@ class WunderBar extends React.PureComponent { onChange={this.onChange} onKeyPress={this.onKeyPress} value={this.state.address} - placeholder={__('Find movies, music, games, and more')} + placeholder={__('Find videos, music, games, and more')} />
); From 0f458b66d9d44fc69bea5729aa42d6e85deed7c9 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 4 Jan 2018 16:47:18 -0500 Subject: [PATCH 39/52] =?UTF-8?q?Bump=20version:=200.19.3=20=E2=86=92=200.?= =?UTF-8?q?19.4rc1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 0e0eb1a42..609a7ce07 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.3 +current_version = 0.19.4rc1 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/package.json b/package.json index 98ed0ee9d..e5b01cd30 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.3", + "version": "0.19.4rc1", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": { From e6bd648116ff4a63a8c25799e211ece9a3caccbc Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 4 Jan 2018 17:05:29 -0500 Subject: [PATCH 40/52] use one icon component and add padded prop --- src/renderer/component/common.js | 17 ----------------- src/renderer/component/fileCard/view.jsx | 4 ++-- .../component/fileDownloadLink/view.jsx | 3 ++- src/renderer/component/form.js | 2 +- src/renderer/component/icon/view.jsx | 16 +++++++++++++--- src/renderer/component/inviteList/view.jsx | 2 +- src/renderer/component/menu.js | 2 +- src/renderer/component/uriIndicator/view.jsx | 2 +- src/renderer/component/wunderbar/view.jsx | 2 +- src/renderer/page/discover/view.jsx | 3 ++- src/renderer/page/help/view.jsx | 3 ++- src/renderer/scss/_gui.scss | 4 ++++ 12 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/renderer/component/common.js b/src/renderer/component/common.js index bf4a4d8ce..629d09f57 100644 --- a/src/renderer/component/common.js +++ b/src/renderer/component/common.js @@ -3,23 +3,6 @@ import PropTypes from 'prop-types'; import { formatCredits, formatFullPrice } from 'util/formatCredits'; import lbry from '../lbry.js'; -// component/icon.js -export class Icon extends React.PureComponent { - static propTypes = { - icon: PropTypes.string.isRequired, - className: PropTypes.string, - fixed: 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 ; - } -} - export class TruncatedText extends React.PureComponent { static propTypes = { lines: PropTypes.number, diff --git a/src/renderer/component/fileCard/view.jsx b/src/renderer/component/fileCard/view.jsx index 9a74a49fb..fdc070cf9 100644 --- a/src/renderer/component/fileCard/view.jsx +++ b/src/renderer/component/fileCard/view.jsx @@ -87,8 +87,8 @@ class FileCard extends React.PureComponent {
- {isRewardContent && }{' '} - {fileInfo && } + {isRewardContent && }{' '} + {fileInfo && } diff --git a/src/renderer/component/fileDownloadLink/view.jsx b/src/renderer/component/fileDownloadLink/view.jsx index 2c4aba0dc..4595b36d9 100644 --- a/src/renderer/component/fileDownloadLink/view.jsx +++ b/src/renderer/component/fileDownloadLink/view.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import { Icon, BusyMessage } from 'component/common'; +import { BusyMessage } from 'component/common'; +import Icon from 'component/icon'; import Link from 'component/link'; class FileDownloadLink extends React.PureComponent { diff --git a/src/renderer/component/form.js b/src/renderer/component/form.js index 135df952d..c13619b1a 100644 --- a/src/renderer/component/form.js +++ b/src/renderer/component/form.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import FormField from 'component/formField'; -import { Icon } from 'component/common.js'; +import Icon from 'component/icon'; let formFieldCounter = 0; diff --git a/src/renderer/component/icon/view.jsx b/src/renderer/component/icon/view.jsx index d017bf5b5..795a1b241 100644 --- a/src/renderer/component/icon/view.jsx +++ b/src/renderer/component/icon/view.jsx @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import * as icons from 'constants/icons'; +import classnames from 'classnames'; export default class Icon extends React.PureComponent { static propTypes = { @@ -30,10 +31,19 @@ export default class Icon extends React.PureComponent { } render() { - const className = this.getIconClass(), - title = this.getIconTitle(); + const { icon, fixed, className, leftPad } = this.props; + const iconClass = this.getIconClass(); + const title = this.getIconTitle(); - const spanClassName = `icon ${className}${this.props.fixed ? ' icon-fixed-width ' : ''}`; + const spanClassName = classnames( + 'icon', + iconClass, + { + 'icon-fixed-width': fixed, + 'icon--left-pad': leftPad, + }, + className + ); return ; } diff --git a/src/renderer/component/inviteList/view.jsx b/src/renderer/component/inviteList/view.jsx index 7cd5bfcb8..c339cfd1b 100644 --- a/src/renderer/component/inviteList/view.jsx +++ b/src/renderer/component/inviteList/view.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Icon } from 'component/common'; +import Icon from 'component/icon'; import RewardLink from 'component/rewardLink'; import rewards from 'rewards.js'; diff --git a/src/renderer/component/menu.js b/src/renderer/component/menu.js index c7c2e38de..e070f8711 100644 --- a/src/renderer/component/menu.js +++ b/src/renderer/component/menu.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Icon } from './common.js'; +import Icon from 'component/icon'; import Link from 'component/link'; export class DropDownMenuItem extends React.PureComponent { diff --git a/src/renderer/component/uriIndicator/view.jsx b/src/renderer/component/uriIndicator/view.jsx index c7d5272dc..704769250 100644 --- a/src/renderer/component/uriIndicator/view.jsx +++ b/src/renderer/component/uriIndicator/view.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Icon } from 'component/common'; +import Icon from 'component/icon'; import Link from 'component/link'; import lbryuri from 'lbryuri'; import classnames from 'classnames'; diff --git a/src/renderer/component/wunderbar/view.jsx b/src/renderer/component/wunderbar/view.jsx index 9c3725bed..f332a11ec 100644 --- a/src/renderer/component/wunderbar/view.jsx +++ b/src/renderer/component/wunderbar/view.jsx @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import lbryuri from 'lbryuri.js'; -import { Icon } from 'component/common.js'; +import Icon from 'component/icon'; import { parseQueryParams } from 'util/query_params'; class WunderBar extends React.PureComponent { diff --git a/src/renderer/page/discover/view.jsx b/src/renderer/page/discover/view.jsx index 53bc5afaa..52b841bab 100644 --- a/src/renderer/page/discover/view.jsx +++ b/src/renderer/page/discover/view.jsx @@ -2,7 +2,8 @@ import React from 'react'; import ReactDOM from 'react-dom'; import lbryuri from 'lbryuri'; import FileCard from 'component/fileCard'; -import { Icon, BusyMessage } from 'component/common.js'; +import { BusyMessage } from 'component/common.js'; +import Icon from 'component/icon'; import ToolTip from 'component/tooltip.js'; import SubHeader from 'component/subHeader'; import classnames from 'classnames'; diff --git a/src/renderer/page/help/view.jsx b/src/renderer/page/help/view.jsx index 8d1ca882c..bb22e6fe5 100644 --- a/src/renderer/page/help/view.jsx +++ b/src/renderer/page/help/view.jsx @@ -3,7 +3,8 @@ import React from 'react'; import lbry from 'lbry.js'; import Link from 'component/link'; import SubHeader from 'component/subHeader'; -import { BusyMessage, Icon } from 'component/common'; +import { BusyMessage } from 'component/common'; +import Icon from 'component/icon'; class HelpPage extends React.PureComponent { constructor(props) { diff --git a/src/renderer/scss/_gui.scss b/src/renderer/scss/_gui.scss index da3f5334c..92b82d146 100644 --- a/src/renderer/scss/_gui.scss +++ b/src/renderer/scss/_gui.scss @@ -81,6 +81,10 @@ body { text-align: center; } +.icon--left-pad { + padding-left: 3px; +} + h2 { font-size: 1.75em; } From d83f96668fd45fdab02f0803730f4153d306fa23 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Thu, 4 Jan 2018 17:57:40 -0500 Subject: [PATCH 41/52] =?UTF-8?q?Bump=20version:=200.19.4rc1=20=E2=86=92?= =?UTF-8?q?=200.19.5rc1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 609a7ce07..3541e345d 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.4rc1 +current_version = 0.19.5rc1 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/package.json b/package.json index e5b01cd30..6bf14377b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.4rc1", + "version": "0.19.5rc1", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": { From 345badb0497fc687b8bbcf8d3adf6119e3ef72aa Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Fri, 5 Jan 2018 14:27:58 -0500 Subject: [PATCH 42/52] store position by outpoint --- .../component/video/internal/player.jsx | 7 +++--- src/renderer/component/video/view.jsx | 4 +++- src/renderer/redux/actions/media.js | 23 ++++++++++++------- src/renderer/redux/reducers/media.js | 4 ++-- src/renderer/redux/selectors/media.js | 7 +++--- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/renderer/component/video/internal/player.jsx b/src/renderer/component/video/internal/player.jsx index fdb5dccc3..521de6470 100644 --- a/src/renderer/component/video/internal/player.jsx +++ b/src/renderer/component/video/internal/player.jsx @@ -35,7 +35,8 @@ class VideoPlayer extends React.PureComponent { changeVolume, volume, position, - id, + claim, + uri, } = this.props; const loadedMetadata = e => { @@ -70,11 +71,11 @@ class VideoPlayer extends React.PureComponent { document.addEventListener("keydown", this.togglePlayListener); const mediaElement = this.refs.media.children[0]; if (mediaElement) { - mediaElement.currentTime = position; + mediaElement.currentTime = position || 0; mediaElement.addEventListener("play", () => this.props.doPlay()); mediaElement.addEventListener("pause", () => this.props.doPause()); mediaElement.addEventListener("timeupdate", () => - this.props.savePosition(id, mediaElement.currentTime) + this.props.savePosition(claim.claim_id, mediaElement.currentTime) ); mediaElement.addEventListener("click", this.togglePlayListener); mediaElement.addEventListener( diff --git a/src/renderer/component/video/view.jsx b/src/renderer/component/video/view.jsx index 1daf4e00e..74f896bc1 100644 --- a/src/renderer/component/video/view.jsx +++ b/src/renderer/component/video/view.jsx @@ -62,6 +62,7 @@ class Video extends React.PureComponent { savePosition, mediaPaused, mediaPosition, + positions, } = this.props; const isPlaying = playingUri === uri; @@ -119,7 +120,8 @@ class Video extends React.PureComponent { doPlay={doPlay} doPause={doPause} savePosition={savePosition} - id={claim.claim_id} + claim={claim} + uri={uri} paused={mediaPaused} position={mediaPosition} /> diff --git a/src/renderer/redux/actions/media.js b/src/renderer/redux/actions/media.js index 6cdc6815e..9971c4a45 100644 --- a/src/renderer/redux/actions/media.js +++ b/src/renderer/redux/actions/media.js @@ -2,6 +2,7 @@ import * as actions from "constants/action_types"; import type { Action, Dispatch } from "redux/reducers/media"; import lbry from "lbry"; +import { makeSelectClaimForUri } from "redux/selectors/claims"; export const doPlay = () => (dispatch: Dispatch) => dispatch({ @@ -13,11 +14,17 @@ export const doPause = () => (dispatch: Dispatch) => type: actions.MEDIA_PAUSE, }); -export const savePosition = (id: String, position: String) => ( - dispatch: Dispatch -) => - dispatch({ - type: actions.MEDIA_POSITION, - id, - position, - }); +export function savePosition(claimId, position) { + return function(dispatch: Dispatch, getState: Function) { + const state = getState(); + const claim = state.claims.byId[claimId]; + const outpoint = `${claim.txid}:${claim.nout}`; + dispatch({ + type: actions.MEDIA_POSITION, + data: { + outpoint, + position, + }, + }); + }; +} diff --git a/src/renderer/redux/reducers/media.js b/src/renderer/redux/reducers/media.js index 92d5f4115..7e3bb9591 100644 --- a/src/renderer/redux/reducers/media.js +++ b/src/renderer/redux/reducers/media.js @@ -27,12 +27,12 @@ export default handleActions( }), [actions.MEDIA_POSITION]: (state: MediaState, action: Action) => { - const { id, position } = action; + const { outpoint, position } = action.data; return { ...state, positions: { ...state.positions, - [id]: position, + [outpoint]: position, }, }; }, diff --git a/src/renderer/redux/selectors/media.js b/src/renderer/redux/selectors/media.js index a3418775d..9ef16abaf 100644 --- a/src/renderer/redux/selectors/media.js +++ b/src/renderer/redux/selectors/media.js @@ -1,6 +1,7 @@ import * as settings from "constants/settings"; import { createSelector } from "reselect"; import lbryuri from "lbryuri"; +import { makeSelectClaimForUri } from "redux/selectors/claims"; const _selectState = state => state.media || {}; @@ -10,7 +11,7 @@ export const selectMediaPaused = createSelector( ); export const makeSelectMediaPositionForUri = uri => - createSelector(_selectState, state => { - const obj = lbryuri.parse(uri); - return state.positions[obj.claimId] || null; + createSelector(_selectState, makeSelectClaimForUri(uri), (state, claim) => { + const outpoint = `${claim.txid}:${claim.nout}`; + return state.positions[outpoint] || null; }); From 504c5469e398221a6f2ba7f3df7cfefc1b215a6e Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Fri, 5 Jan 2018 14:29:25 -0500 Subject: [PATCH 43/52] safely type params in position selector --- src/renderer/redux/actions/media.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/redux/actions/media.js b/src/renderer/redux/actions/media.js index 9971c4a45..d3076ed75 100644 --- a/src/renderer/redux/actions/media.js +++ b/src/renderer/redux/actions/media.js @@ -14,7 +14,7 @@ export const doPause = () => (dispatch: Dispatch) => type: actions.MEDIA_PAUSE, }); -export function savePosition(claimId, position) { +export function savePosition(claimId: String, position: Number) { return function(dispatch: Dispatch, getState: Function) { const state = getState(); const claim = state.claims.byId[claimId]; From 0cfc9ab32c7a11a3c16f06a83050163e86655bb9 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Fri, 5 Jan 2018 14:31:58 -0500 Subject: [PATCH 44/52] remove old positions variable --- src/renderer/component/video/view.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/renderer/component/video/view.jsx b/src/renderer/component/video/view.jsx index 74f896bc1..a924cf262 100644 --- a/src/renderer/component/video/view.jsx +++ b/src/renderer/component/video/view.jsx @@ -62,7 +62,6 @@ class Video extends React.PureComponent { savePosition, mediaPaused, mediaPosition, - positions, } = this.props; const isPlaying = playingUri === uri; From 566fb2e0b56e80a80b5909b07ea106e80731d424 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Fri, 5 Jan 2018 15:14:12 -0500 Subject: [PATCH 45/52] rename id param to claimId --- src/renderer/component/video/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/renderer/component/video/index.js b/src/renderer/component/video/index.js index cc01f032a..8c0a91289 100644 --- a/src/renderer/component/video/index.js +++ b/src/renderer/component/video/index.js @@ -44,7 +44,8 @@ const perform = dispatch => ({ changeVolume: volume => dispatch(doChangeVolume(volume)), doPlay: () => dispatch(doPlay()), doPause: () => dispatch(doPause()), - savePosition: (id, position) => dispatch(savePosition(id, position)), + savePosition: (claimId, position) => + dispatch(savePosition(claimId, position)), }); export default connect(select, perform)(Video); From 3e25b33fedb0b4418065cf8ee33a60312a311bee Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 5 Jan 2018 14:09:57 -0800 Subject: [PATCH 46/52] Revert to version 19.3 --- .bumpversion.cfg | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 3541e345d..0e0eb1a42 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.5rc1 +current_version = 0.19.3 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/package.json b/package.json index 6bf14377b..98ed0ee9d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.5rc1", + "version": "0.19.3", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": { From b3fb8479128212a4c052d701980c3abcaabba965 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 5 Jan 2018 14:16:45 -0800 Subject: [PATCH 47/52] =?UTF-8?q?Bump=20version:=200.19.3=20=E2=86=92=200.?= =?UTF-8?q?19.4rc1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 0e0eb1a42..609a7ce07 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.3 +current_version = 0.19.4rc1 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/package.json b/package.json index 98ed0ee9d..e5b01cd30 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.3", + "version": "0.19.4rc1", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": { From 60772d0a7484a2da69cbbb78c44d514e0a44de0a Mon Sep 17 00:00:00 2001 From: Igor Gassmann Date: Fri, 5 Jan 2018 19:25:33 -0300 Subject: [PATCH 48/52] Fix right click bug --- src/main/index.js | 4 +++- src/main/menu/contextMenu.js | 16 +++------------- src/renderer/index.js | 7 +------ 3 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/main/index.js b/src/main/index.js index 383be184d..30a78c3e6 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -10,9 +10,9 @@ import ChildProcess from 'child_process'; import Assert from 'assert'; import { app, BrowserWindow, globalShortcut, ipcMain, Menu, Tray } from 'electron'; import mainMenu from './menu/mainMenu'; +import contextMenu from './menu/contextMenu'; const localVersion = app.getVersion(); -export { contextMenu as Default } from './menu/contextMenu'; // Debug configs const isDevelopment = process.env.NODE_ENV === 'development'; @@ -526,3 +526,5 @@ ipcMain.on('get-auth-token', event => { ipcMain.on('set-auth-token', (event, token) => { Keytar.setPassword('LBRY', 'auth_token', token ? token.toString().trim() : null); }); + +export { contextMenu }; diff --git a/src/main/menu/contextMenu.js b/src/main/menu/contextMenu.js index ad33c6bc2..e24885ec2 100644 --- a/src/main/menu/contextMenu.js +++ b/src/main/menu/contextMenu.js @@ -1,18 +1,8 @@ import { Menu } from 'electron'; -const contextMenuTemplate = [ - { - role: 'cut', - }, - { - role: 'copy', - }, - { - role: 'paste', - }, -]; +const contextMenuTemplate = [{ role: 'cut' }, { role: 'copy' }, { role: 'paste' }]; -export default function contextMenu(win, posX, posY, showDevItems) { +export default (win, posX, posY, showDevItems) => { const template = contextMenuTemplate.slice(); if (showDevItems) { template.push({ @@ -27,4 +17,4 @@ export default function contextMenu(win, posX, posY, showDevItems) { } Menu.buildFromTemplate(template).popup(win); -} +}; diff --git a/src/renderer/index.js b/src/renderer/index.js index 19350e8ce..fd6dcc1f7 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -20,12 +20,7 @@ import app from './app'; const { contextMenu } = remote.require('./main.js'); window.addEventListener('contextmenu', event => { - contextMenu.showContextMenu( - remote.getCurrentWindow(), - event.x, - event.y, - app.env === 'development' - ); + contextMenu(remote.getCurrentWindow(), event.x, event.y, app.env === 'development'); event.preventDefault(); }); From 5765c6c1ee05acf016c3001ab89aefbbcd20d1e5 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Fri, 5 Jan 2018 18:36:03 -0500 Subject: [PATCH 49/52] remove comment --- src/renderer/component/video/internal/player.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/renderer/component/video/internal/player.jsx b/src/renderer/component/video/internal/player.jsx index 521de6470..6740c5d2f 100644 --- a/src/renderer/component/video/internal/player.jsx +++ b/src/renderer/component/video/internal/player.jsx @@ -23,7 +23,6 @@ class VideoPlayer extends React.PureComponent { componentWillReceiveProps(next) { const el = this.refs.media.children[0]; if (!this.props.paused && next.paused && !el.paused) el.pause(); - // if (this.props.paused && !next.paused && el.paused) el.play(); } componentDidMount() { From d3047a741a7556ccd29e19c29bece05e78c2e4a8 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Fri, 5 Jan 2018 19:04:12 -0500 Subject: [PATCH 50/52] remove ENV statement --- src/renderer/store.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/renderer/store.js b/src/renderer/store.js index 7af0ce7ea..ca6db3afd 100644 --- a/src/renderer/store.js +++ b/src/renderer/store.js @@ -21,8 +21,6 @@ import localForage from 'localforage'; import { createStore, applyMiddleware, compose, combineReducers } from 'redux'; import thunk from 'redux-thunk'; -const env = process.env.NODE_ENV || 'production'; - function isFunction(object) { return typeof object === 'function'; } From d89f87fa73a3b48484f22e7abcf7b3130c03592d Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 5 Jan 2018 21:22:51 -0800 Subject: [PATCH 51/52] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5909b74bb..1c1f049c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,15 +8,17 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added - * + * Video state tracking in redux - developer only (#890) * ### Changed - * + * Improved text content in app (#921) * ### Fixed - * + * Right click works in the app again (#928) + * Icons are now the rights size (#925) + * Fixed tip sending error (#918) * ### Deprecated From f903b75b71e6d0ec99f53da9330476d047845afc Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 5 Jan 2018 21:25:12 -0800 Subject: [PATCH 52/52] =?UTF-8?q?Bump=20version:=200.19.4rc1=20=E2=86=92?= =?UTF-8?q?=200.19.4rc2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 609a7ce07..b0d45e6e6 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.4rc1 +current_version = 0.19.4rc2 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/package.json b/package.json index e5b01cd30..166286b06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.4rc1", + "version": "0.19.4rc2", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": {