From d43dd7882192f0481df8126016181eedcd0aa946 Mon Sep 17 00:00:00 2001
From: Travis Eden <daovist@gmail.com>
Date: Thu, 12 Jul 2018 15:37:01 -0400
Subject: [PATCH 1/5] suppress load video error; disable autoplay per-video
 after download failure

---
 src/renderer/component/fileViewer/index.js |  2 ++
 src/renderer/component/fileViewer/view.jsx | 16 ++++++++--
 src/renderer/redux/actions/content.js      | 36 +++++++++++++---------
 src/renderer/redux/selectors/file_info.js  |  8 +++--
 4 files changed, 43 insertions(+), 19 deletions(-)

diff --git a/src/renderer/component/fileViewer/index.js b/src/renderer/component/fileViewer/index.js
index 00ef7c3c0..2e77b38d4 100644
--- a/src/renderer/component/fileViewer/index.js
+++ b/src/renderer/component/fileViewer/index.js
@@ -17,6 +17,7 @@ import {
 import { makeSelectClientSetting, selectShowNsfw } from 'redux/selectors/settings';
 import { selectMediaPaused, makeSelectMediaPositionForUri } from 'redux/selectors/media';
 import { selectPlayingUri } from 'redux/selectors/content';
+import { selectFileInfoErrors } from 'redux/selectors/file_info';
 import FileViewer from './view';
 
 const select = (state, props) => ({
@@ -34,6 +35,7 @@ const select = (state, props) => ({
   mediaPosition: makeSelectMediaPositionForUri(props.uri)(state),
   autoplay: makeSelectClientSetting(settings.AUTOPLAY)(state),
   searchBarFocused: selectSearchBarFocused(state),
+  fileInfoErrors: selectFileInfoErrors(state)
 });
 
 const perform = dispatch => ({
diff --git a/src/renderer/component/fileViewer/view.jsx b/src/renderer/component/fileViewer/view.jsx
index 2a0d9f53d..0a16d9f92 100644
--- a/src/renderer/component/fileViewer/view.jsx
+++ b/src/renderer/component/fileViewer/view.jsx
@@ -79,10 +79,22 @@ class FileViewer extends React.PureComponent<Props> {
     }
   }
 
+  // do not play when state.content.errors[uri]
   handleAutoplay = (props: Props) => {
-    const { autoplay, playingUri, fileInfo, costInfo, isDownloading, uri, play, metadata } = props;
+    const {
+      autoplay,
+      playingUri,
+      fileInfo,
+      costInfo,
+      isDownloading,
+      uri,
+      play,
+      metadata,
+      fileInfoErrors,
+    } = props;
 
-    const playable = autoplay && playingUri !== uri && metadata && !metadata.nsfw;
+    const playable =
+      autoplay && playingUri !== uri && metadata && !metadata.nsfw && !(uri in fileInfoErrors);
 
     if (playable && costInfo && costInfo.cost === 0 && !fileInfo && !isDownloading) {
       play(uri);
diff --git a/src/renderer/redux/actions/content.js b/src/renderer/redux/actions/content.js
index f16d89f6f..c50bff457 100644
--- a/src/renderer/redux/actions/content.js
+++ b/src/renderer/redux/actions/content.js
@@ -171,7 +171,7 @@ export function doUpdateLoadStatus(uri, outpoint) {
       } else {
         // ready to play
         const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo;
-        const progress = writtenBytes / totalBytes * 100;
+        const progress = (writtenBytes / totalBytes) * 100;
 
         dispatch({
           type: ACTIONS.DOWNLOADING_PROGRESSED,
@@ -259,29 +259,37 @@ export function doLoadVideo(uri) {
           streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout';
 
         if (timeout) {
-          dispatch(doSetPlayingUri(null));
-          dispatch({
-            type: ACTIONS.LOADING_VIDEO_FAILED,
-            data: { uri },
-          });
-
-          dispatch(doNotify({ id: MODALS.FILE_TIMEOUT }, { uri }));
+          dispatch(handleLoadVideoError(uri, 'timeout'));
         } else {
           dispatch(doDownloadFile(uri, streamInfo));
         }
       })
       .catch(() => {
-        dispatch(doSetPlayingUri(null));
-        dispatch({
-          type: ACTIONS.LOADING_VIDEO_FAILED,
-          data: { uri },
-        });
+        dispatch(handleLoadVideoError(uri));
+      });
+  };
+}
+
+function handleLoadVideoError(uri, errorType = '') {
+  return (dispatch, getState) => {
+    // suppress error when another media is playing
+    const { playingUri } = getState().content;
+    if (!playingUri || playingUri === uri) {
+      dispatch({
+        type: ACTIONS.LOADING_VIDEO_FAILED,
+        data: { uri },
+      });
+      dispatch(doSetPlayingUri(null));
+      if (errorType === 'timeout') {
+        doNotify({ id: MODALS.FILE_TIMEOUT }, { uri });
+      } else {
         dispatch(
           doAlertError(
             `Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.io/faq/support for support.`
           )
         );
-      });
+      }
+    }
   };
 }
 
diff --git a/src/renderer/redux/selectors/file_info.js b/src/renderer/redux/selectors/file_info.js
index 801ced0b4..d49f2e9a2 100644
--- a/src/renderer/redux/selectors/file_info.js
+++ b/src/renderer/redux/selectors/file_info.js
@@ -3,9 +3,9 @@ import {
   selectIsFetchingClaimListMine,
   selectMyClaims,
   selectClaimsById,
-} from 'redux/selectors/claims';
+  buildURI,
+} from 'lbry-redux';
 import { createSelector } from 'reselect';
-import { buildURI } from 'lbryURI';
 
 export const selectState = state => state.fileInfo || {};
 
@@ -97,7 +97,7 @@ export const selectTotalDownloadProgress = createSelector(selectDownloadingFileI
   const progress = [];
 
   fileInfos.forEach(fileInfo => {
-    progress.push(fileInfo.written_bytes / fileInfo.total_bytes * 100);
+    progress.push((fileInfo.written_bytes / fileInfo.total_bytes) * 100);
   });
 
   const totalProgress = progress.reduce((a, b) => a + b, 0);
@@ -195,3 +195,5 @@ export const selectSearchDownloadUris = query =>
         })
       : null;
   });
+
+export const selectFileInfoErrors = createSelector(selectState, state => state.errors || {});

From 17ca490db40156dac7ee5f3e98497a7349f36137 Mon Sep 17 00:00:00 2001
From: Travis Eden <daovist@gmail.com>
Date: Wed, 18 Jul 2018 10:29:43 -0400
Subject: [PATCH 2/5] display download error only when that uri is playing

---
 src/renderer/redux/actions/content.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/renderer/redux/actions/content.js b/src/renderer/redux/actions/content.js
index c50bff457..04808b6e1 100644
--- a/src/renderer/redux/actions/content.js
+++ b/src/renderer/redux/actions/content.js
@@ -274,7 +274,7 @@ function handleLoadVideoError(uri, errorType = '') {
   return (dispatch, getState) => {
     // suppress error when another media is playing
     const { playingUri } = getState().content;
-    if (!playingUri || playingUri === uri) {
+    if (playingUri && playingUri === uri) {
       dispatch({
         type: ACTIONS.LOADING_VIDEO_FAILED,
         data: { uri },

From bc68b75012d0e7eab061238f7c83d88f50550ef3 Mon Sep 17 00:00:00 2001
From: Travis Eden <daovist@gmail.com>
Date: Wed, 18 Jul 2018 10:41:14 -0400
Subject: [PATCH 3/5] prevent handleAutoplay in componentDidUpdate

---
 src/renderer/component/fileViewer/view.jsx | 34 +++++++++-------------
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/src/renderer/component/fileViewer/view.jsx b/src/renderer/component/fileViewer/view.jsx
index 0a16d9f92..406c25186 100644
--- a/src/renderer/component/fileViewer/view.jsx
+++ b/src/renderer/component/fileViewer/view.jsx
@@ -17,6 +17,9 @@ type Props = {
     download_path: string,
     completed: boolean,
   },
+  fileInfoErrors: ?{
+    [string]: boolean,
+  },
   metadata: ?{
     nsfw: boolean,
     thumbnail: string,
@@ -55,14 +58,17 @@ class FileViewer extends React.PureComponent<Props> {
     window.addEventListener('keydown', this.handleKeyDown);
   }
 
-  componentWillReceiveProps(nextProps: Props) {
+  componentDidUpdate(prev: Props) {
     if (
-      this.props.autoplay !== nextProps.autoplay ||
-      this.props.fileInfo !== nextProps.fileInfo ||
-      this.props.isDownloading !== nextProps.isDownloading ||
-      this.props.playingUri !== nextProps.playingUri
+      this.props.autoplay !== prev.autoplay ||
+      this.props.fileInfo !== prev.fileInfo ||
+      this.props.isDownloading !== prev.isDownloading ||
+      this.props.playingUri !== prev.playingUri
     ) {
-      this.handleAutoplay(nextProps);
+      // suppress autoplay after download error
+      if (!(this.props.uri in this.props.fileInfoErrors)) {
+        this.handleAutoplay(this.props);
+      }
     }
   }
 
@@ -79,22 +85,10 @@ class FileViewer extends React.PureComponent<Props> {
     }
   }
 
-  // do not play when state.content.errors[uri]
   handleAutoplay = (props: Props) => {
-    const {
-      autoplay,
-      playingUri,
-      fileInfo,
-      costInfo,
-      isDownloading,
-      uri,
-      play,
-      metadata,
-      fileInfoErrors,
-    } = props;
+    const { autoplay, playingUri, fileInfo, costInfo, isDownloading, uri, play, metadata } = props;
 
-    const playable =
-      autoplay && playingUri !== uri && metadata && !metadata.nsfw && !(uri in fileInfoErrors);
+    const playable = autoplay && playingUri !== uri && metadata && !metadata.nsfw;
 
     if (playable && costInfo && costInfo.cost === 0 && !fileInfo && !isDownloading) {
       play(uri);

From 09a637d5725eee2b5d0ff31e82ad9b9e4604c129 Mon Sep 17 00:00:00 2001
From: Sean Yesmunt <sean@lbry.io>
Date: Thu, 19 Jul 2018 09:59:05 -0400
Subject: [PATCH 4/5] update lbry-redux

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index cfcc220bd..303331a47 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,7 @@
     "formik": "^0.10.4",
     "hast-util-sanitize": "^1.1.2",
     "keytar": "^4.2.1",
-    "lbry-redux": "lbryio/lbry-redux#177ef2c1916f9672e713267500e447d671ae1bc3",
+    "lbry-redux": "lbryio/lbry-redux#e0909b08647a790d155f3189b9f9bf0b3e55bd17",
     "localforage": "^1.7.1",
     "mime": "^2.3.1",
     "mixpanel-browser": "^2.17.1",

From 3b1167c45afef697e24bbcfc533ab33ced78cd50 Mon Sep 17 00:00:00 2001
From: Sean Yesmunt <sean@lbry.io>
Date: Thu, 19 Jul 2018 10:01:25 -0400
Subject: [PATCH 5/5] update changelog

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 26713a24b..0fcdf0a91 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
 
 ### Changed
 
+* Only show video error modal if you are on the video page & don't retry to play failed videos ([#1768](https://github.com/lbryio/lbry-desktop/pull/1768))
 
 
 ## [0.22.2] - 2018-07-09