From b99d58c3f9a9ad67d26cf38cdf7d97865fe03489 Mon Sep 17 00:00:00 2001 From: 6ea86b96 <6ea86b96@gmail.com> Date: Fri, 21 Jul 2017 15:02:29 +0700 Subject: [PATCH 1/8] Track downloading files by outpoint --- ui/js/actions/content.js | 7 ++++--- ui/js/reducers/file_info.js | 18 +++++++++--------- ui/js/selectors/file_info.js | 24 ++++++++++++++---------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/ui/js/actions/content.js b/ui/js/actions/content.js index f46a1fa33..6c2052aca 100644 --- a/ui/js/actions/content.js +++ b/ui/js/actions/content.js @@ -5,7 +5,7 @@ import lbryuri from "lbryuri"; import { selectBalance } from "selectors/wallet"; import { selectFileInfoForUri, - selectUrisDownloading, + selectDownloadingByOutpoint, } from "selectors/file_info"; import { selectResolvingUris } from "selectors/content"; import { selectCostInfoForUri } from "selectors/cost_info"; @@ -265,8 +265,9 @@ export function doPurchaseUri(uri, purchaseModalName) { const state = getState(); const balance = selectBalance(state); const fileInfo = selectFileInfoForUri(state, { uri }); - const downloadingByUri = selectUrisDownloading(state); - const alreadyDownloading = !!downloadingByUri[uri]; + const downloadingByOutpoint = selectDownloadingByOutpoint(state); + const alreadyDownloading = + fileInfo && !!downloadingByOutpoint[fileInfo.outpoint]; // we already fully downloaded the file. if (fileInfo && fileInfo.completed) { diff --git a/ui/js/reducers/file_info.js b/ui/js/reducers/file_info.js index 500fbdf82..33655aca5 100644 --- a/ui/js/reducers/file_info.js +++ b/ui/js/reducers/file_info.js @@ -58,15 +58,15 @@ reducers[types.DOWNLOADING_STARTED] = function(state, action) { const { uri, outpoint, fileInfo } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); - const newDownloading = Object.assign({}, state.urisDownloading); + const newDownloading = Object.assign({}, state.downloadingByOutpoin); const newLoading = Object.assign({}, state.urisLoading); - newDownloading[uri] = true; + newDownloading[outpoint] = true; newByOutpoint[outpoint] = fileInfo; delete newLoading[uri]; return Object.assign({}, state, { - urisDownloading: newDownloading, + downloadingByOutpoint: newDownloading, urisLoading: newLoading, byOutpoint: newByOutpoint, }); @@ -76,14 +76,14 @@ reducers[types.DOWNLOADING_PROGRESSED] = function(state, action) { const { uri, outpoint, fileInfo } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); - const newDownloading = Object.assign({}, state.urisDownloading); + const newDownloading = Object.assign({}, state.downloadingByOutpoint); newByOutpoint[outpoint] = fileInfo; - newDownloading[uri] = true; + newDownloading[outpoint] = true; return Object.assign({}, state, { byOutpoint: newByOutpoint, - urisDownloading: newDownloading, + downloadingByOutpoint: newDownloading, }); }; @@ -91,14 +91,14 @@ reducers[types.DOWNLOADING_COMPLETED] = function(state, action) { const { uri, outpoint, fileInfo } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); - const newDownloading = Object.assign({}, state.urisDownloading); + const newDownloading = Object.assign({}, state.downloadingByOutpoint); newByOutpoint[outpoint] = fileInfo; - delete newDownloading[uri]; + delete newDownloading[outpoint]; return Object.assign({}, state, { byOutpoint: newByOutpoint, - urisDownloading: newDownloading, + downloadingByOutpoint: newDownloading, }); }; diff --git a/ui/js/selectors/file_info.js b/ui/js/selectors/file_info.js index ef469ab02..1b3dc7982 100644 --- a/ui/js/selectors/file_info.js +++ b/ui/js/selectors/file_info.js @@ -39,14 +39,18 @@ export const makeSelectFileInfoForUri = () => { return createSelector(selectFileInfoForUri, fileInfo => fileInfo); }; -export const selectUrisDownloading = createSelector( +export const selectDownloadingByOutpoint = createSelector( _selectState, - state => state.urisDownloading || {} + state => state.downloadingByOutpoint || {} ); const selectDownloadingForUri = (state, props) => { - const byUri = selectUrisDownloading(state); - return byUri[props.uri]; + const byOutpoint = selectDownloadingByOutpoint(state); + const fileInfo = selectFileInfoForUri(state, props); + + if (!fileInfo) return false; + + return byOutpoint[fileInfo.outpoint]; }; export const makeSelectDownloadingForUri = () => { @@ -135,14 +139,14 @@ export const selectFileInfosByUri = createSelector( ); export const selectDownloadingFileInfos = createSelector( - selectUrisDownloading, - selectFileInfosByUri, - (urisDownloading, byUri) => { - const uris = Object.keys(urisDownloading); + selectDownloadingByOutpoint, + selectFileInfosByOutpoint, + (downloadingByOutpoint, fileInfosByOutpoint) => { + const outpoints = Object.keys(downloadingByOutpoint); const fileInfos = []; - uris.forEach(uri => { - const fileInfo = byUri[uri]; + outpoints.forEach(outpoint => { + const fileInfo = fileInfosByOutpoint[outpoint]; if (fileInfo) fileInfos.push(fileInfo); }); From af96d40ead18f5f78d6302acc36684cf52f2f87a Mon Sep 17 00:00:00 2001 From: 6ea86b96 <6ea86b96@gmail.com> Date: Fri, 21 Jul 2017 15:13:45 +0700 Subject: [PATCH 2/8] Remove files from downloading list when they are deleted mid download --- ui/js/actions/file_info.js | 22 ++++++++++++++++++++-- ui/js/component/modalRemoveFile/index.js | 6 +++--- ui/js/reducers/file_info.js | 3 +++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/ui/js/actions/file_info.js b/ui/js/actions/file_info.js index d21df8d2a..9ed2df5a7 100644 --- a/ui/js/actions/file_info.js +++ b/ui/js/actions/file_info.js @@ -10,8 +10,11 @@ import { selectIsFetchingFileList, selectFileInfosByOutpoint, selectUrisLoading, + selectTotalDownloadProgress, } from "selectors/file_info"; -import { doCloseModal } from "actions/app"; +import { doCloseModal, doHistoryBack } from "actions/app"; +import setProgressBar from "util/setProgressBar"; +import batchActions from "util/batchActions"; const { shell } = require("electron"); @@ -119,7 +122,22 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) { }, }); - dispatch(doCloseModal()); + const totalProgress = selectTotalDownloadProgress(getState()); + setProgressBar(totalProgress); + }; +} + +export function doDeleteFileAndGoBack( + fileInfo, + deleteFromComputer, + abandonClaim +) { + return function(dispatch, getState) { + const actions = []; + actions.push(doCloseModal()); + actions.push(doHistoryBack()); + actions.push(doDeleteFile(fileInfo, deleteFromComputer, abandonClaim)); + dispatch(batchActions(...actions)); }; } diff --git a/ui/js/component/modalRemoveFile/index.js b/ui/js/component/modalRemoveFile/index.js index de54514d5..211bdff26 100644 --- a/ui/js/component/modalRemoveFile/index.js +++ b/ui/js/component/modalRemoveFile/index.js @@ -1,8 +1,9 @@ import React from "react"; import { connect } from "react-redux"; import { doCloseModal, doHistoryBack } from "actions/app"; -import { doDeleteFile } from "actions/file_info"; +import { doDeleteFileAndGoBack } from "actions/file_info"; import { makeSelectClaimForUriIsMine } from "selectors/claims"; +import batchActions from "util/batchActions"; import ModalRemoveFile from "./view"; @@ -19,8 +20,7 @@ const makeSelect = () => { const perform = dispatch => ({ closeModal: () => dispatch(doCloseModal()), deleteFile: (fileInfo, deleteFromComputer, abandonClaim) => { - dispatch(doHistoryBack()); - dispatch(doDeleteFile(fileInfo, deleteFromComputer, abandonClaim)); + dispatch(doDeleteFileAndGoBack(fileInfo, deleteFromComputer, abandonClaim)); }, }); diff --git a/ui/js/reducers/file_info.js b/ui/js/reducers/file_info.js index 33655aca5..cb5221c98 100644 --- a/ui/js/reducers/file_info.js +++ b/ui/js/reducers/file_info.js @@ -106,11 +106,14 @@ reducers[types.FILE_DELETE] = function(state, action) { const { outpoint } = action.data; const newByOutpoint = Object.assign({}, state.byOutpoint); + const downloadingByOutpoint = Object.assign({}, state.downloadingByOutpoint); delete newByOutpoint[outpoint]; + delete downloadingByOutpoint[outpoint]; return Object.assign({}, state, { byOutpoint: newByOutpoint, + downloadingByOutpoint, }); }; From e7daf42e993e899840a9775174e685fc09f58481 Mon Sep 17 00:00:00 2001 From: 6ea86b96 <6ea86b96@gmail.com> Date: Fri, 21 Jul 2017 16:07:03 +0700 Subject: [PATCH 3/8] CHANGELOG --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c35165bef..1a37a87df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,9 @@ Web UI version numbers should always match the corresponding version of LBRY App * Restored feedback on claim amounts * Fixed hiding price input when Free is checked on publish form * Fixed hiding new identity fields on publish form + * Fixed files on downloaded tab not showing download progress + * Fixed downloading files that are deleted not being removed from the downloading list + * Fixed download progress bar not being cleared when a downloading file is deleted ### Deprecated * From 7671787a6352d0beaac8c4d0ef1276a59cf69aba Mon Sep 17 00:00:00 2001 From: 6ea86b96 <6ea86b96@gmail.com> Date: Sun, 23 Jul 2017 15:49:56 +0700 Subject: [PATCH 4/8] Fix refresh after scrolly history changes --- CHANGELOG.md | 1 + ui/js/actions/app.js | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a37a87df..db625587e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * Fixed files on downloaded tab not showing download progress * Fixed downloading files that are deleted not being removed from the downloading list * Fixed download progress bar not being cleared when a downloading file is deleted + * Fixed refresh regression after adding scroll position to history state ### Deprecated * diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index d5014d9ad..871607778 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -14,6 +14,7 @@ import { doFetchDaemonSettings } from "actions/settings"; import { doAuthenticate } from "actions/user"; import { doFileList } from "actions/file_info"; import { toQueryString } from "util/query_params"; +import { parseQueryParams } from "util/query_params"; const { remote, ipcRenderer, shell } = require("electron"); const path = require("path"); @@ -63,6 +64,7 @@ export function doChangePath(path, options = {}) { export function doHistoryBack() { return function(dispatch, getState) { if (!history.state) return; + if (history.state.index === 0) return; history.back(); }; @@ -249,7 +251,9 @@ export function doAlertError(errorList) { export function doDaemonReady() { return function(dispatch, getState) { - history.replaceState({}, document.title, `#/discover`); + const path = window.location.hash || "#/discover"; + const params = parseQueryParams(path.split("?")[1] || ""); + history.replaceState({ params, index: 0 }, document.title, `${path}`); dispatch(doAuthenticate()); dispatch({ type: types.DAEMON_READY, From 7ea5c615bd492e2c7970b4733d43a0302028042e Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg Date: Mon, 24 Jul 2017 09:03:55 -0400 Subject: [PATCH 5/8] remove confusing placeholder, add prompt to check email for code --- ui/js/component/userEmailVerify/view.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/js/component/userEmailVerify/view.jsx b/ui/js/component/userEmailVerify/view.jsx index 5aa656a61..2570eba29 100644 --- a/ui/js/component/userEmailVerify/view.jsx +++ b/ui/js/component/userEmailVerify/view.jsx @@ -35,7 +35,6 @@ class UserEmailVerify extends React.PureComponent { { @@ -46,7 +45,7 @@ class UserEmailVerify extends React.PureComponent { {/* render help separately so it always shows */}

- {__("Email")}{" "} + {__("Check your email for a verification code. Email")}{" "} {" "} {__("if you did not receive or are having trouble with your code.")}

From 4745088eff715fc949c23bdce996a590e76cad12 Mon Sep 17 00:00:00 2001 From: 6ea86b96 <6ea86b96@gmail.com> Date: Tue, 25 Jul 2017 00:31:15 +0700 Subject: [PATCH 6/8] Display the download button for files that are not downloading and have 0 progress --- CHANGELOG.md | 1 + ui/js/component/fileActions/view.jsx | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a37a87df..eb7cc2f37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * Fixed files on downloaded tab not showing download progress * Fixed downloading files that are deleted not being removed from the downloading list * Fixed download progress bar not being cleared when a downloading file is deleted + * Fixed app thinking downloads with 0 progress were downloaded after restart ### Deprecated * diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 64fb859db..ef72463c5 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -118,7 +118,10 @@ class FileActions extends React.PureComponent { />
); - } else if (fileInfo === null && !downloading) { + } else if ( + (fileInfo === null || (fileInfo && fileInfo.written_bytes === 0)) && + !downloading + ) { if (!costInfo) { content = ; } else { From 9f99fa42fedab4c843823dfb2d1c4ad00981909b Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg Date: Mon, 24 Jul 2017 16:10:57 -0400 Subject: [PATCH 7/8] rotate windows signing cert --- build/build.ps1 | 6 +++--- build/lbry2.pfx.enc | Bin 5968 -> 0 bytes build/lbry3.pfx.enc | Bin 0 -> 5408 bytes 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 build/lbry2.pfx.enc create mode 100644 build/lbry3.pfx.enc diff --git a/build/build.ps1 b/build/build.ps1 index 6c93b172c..569fbd875 100644 --- a/build/build.ps1 +++ b/build/build.ps1 @@ -46,8 +46,8 @@ dir dist # verify that binary was built/named correctly # sign binary nuget install secure-file -ExcludeVersion -secure-file\tools\secure-file -decrypt build\lbry2.pfx.enc -secret "$env:pfx_key" -& ${env:SIGNTOOL_PATH} sign /f build\lbry2.pfx /p "$env:key_pass" /tr http://tsa.starfieldtech.com /td SHA256 /fd SHA256 dist\*.exe +secure-file\tools\secure-file -decrypt build\lbry3.pfx.enc -secret "$env:pfx_key" +& ${env:SIGNTOOL_PATH} sign /f build\lbry3.pfx /p "$env:key_pass" /tr http://tsa.starfieldtech.com /td SHA256 /fd SHA256 dist\*.exe -python build\upload_assets.py \ No newline at end of file +python build\upload_assets.py diff --git a/build/lbry2.pfx.enc b/build/lbry2.pfx.enc deleted file mode 100644 index 46e52260aab51183e669e77f96edbe1a463bf391..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5968 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≫?re#eh04 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
H9wcEVIQLC;{_Lrhw!1?O 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 KtknZI2*A(0C1wQx literal 0 HcmV?d00001 From 0f4bc36bcd69ceb0efc108d95c3b3c92483568a0 Mon Sep 17 00:00:00 2001 From: hackrush Date: Sat, 22 Jul 2017 14:40:37 +0530 Subject: [PATCH 8/8] The URL name is automatically suggested. Fixes #347 minor clean up --- CHANGELOG.md | 1 + ui/js/component/publishForm/view.jsx | 17 +++++++++++++++++ ui/js/lbry.js | 2 +- ui/js/lbryuri.js | 6 ++++-- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f86745569..477ed8013 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * Support markdown makeup in claim description * Replaced free speech flag (used when image is missing) with labeled color tiles * Added a loading message to file actions + * URL is auto suggested in Publish Page ### Changed * Publishes now uses claims rather than files diff --git a/ui/js/component/publishForm/view.jsx b/ui/js/component/publishForm/view.jsx index e73038e16..970787205 100644 --- a/ui/js/component/publishForm/view.jsx +++ b/ui/js/component/publishForm/view.jsx @@ -43,6 +43,7 @@ class PublishForm extends React.PureComponent { creatingChannel: false, modal: null, isFee: false, + customUrl: false, }; } @@ -203,6 +204,9 @@ class PublishForm extends React.PureComponent { handleNameChange(event) { var rawName = event.target.value; + this.setState({ + customUrl: Boolean(rawName.length), + }); this.nameChanged(rawName); } @@ -445,11 +449,24 @@ class PublishForm extends React.PureComponent { onFileChange() { if (this.refs.file.getValue()) { this.setState({ hasFile: true }); + if (!this.state.customUrl) { + let fileName = this._getFileName(this.refs.file.getValue()); + this.nameChanged(fileName); + } } else { this.setState({ hasFile: false }); } } + _getFileName(fileName) { + const path = require("path"); + const extension = path.extname(fileName); + + fileName = path.basename(fileName, extension); + fileName = fileName.replace(lbryuri.REGEXP_INVALID_URI, ""); + return fileName; + } + getNameBidHelpText() { if (this.state.prefillDone) { return __("Existing claim data was prefilled"); diff --git a/ui/js/lbry.js b/ui/js/lbry.js index 7409bdde4..e6a014ae2 100644 --- a/ui/js/lbry.js +++ b/ui/js/lbry.js @@ -296,7 +296,7 @@ lbry.formatCredits = function(amount, precision) { lbry.formatName = function(name) { // Converts LBRY name to standard format (all lower case, no special characters, spaces replaced by dashes) name = name.replace("/s+/g", "-"); - name = name.toLowerCase().replace(/[^a-z0-9\-]/g, ""); + name = name.toLowerCase().replace(lbryuri.REGEXP_INVALID_URI, ""); return name; }; diff --git a/ui/js/lbryuri.js b/ui/js/lbryuri.js index 42a825949..a7f43890a 100644 --- a/ui/js/lbryuri.js +++ b/ui/js/lbryuri.js @@ -3,6 +3,8 @@ const CLAIM_ID_MAX_LEN = 40; const lbryuri = {}; +lbryuri.REGEXP_INVALID_URI = /[^A-Za-z0-9-]/g; + /** * Parses a LBRY name into its component parts. Throws errors with user-friendly * messages for invalid names. @@ -70,7 +72,7 @@ lbryuri.parse = function(uri, requireProto = false) { contentName = path; } - const nameBadChars = (channelName || name).match(/[^A-Za-z0-9-]/g); + const nameBadChars = (channelName || name).match(lbryuri.REGEXP_INVALID_URI); if (nameBadChars) { throw new Error( __( @@ -119,7 +121,7 @@ lbryuri.parse = function(uri, requireProto = false) { throw new Error(__("Only channel URIs may have a path.")); } - const pathBadChars = path.match(/[^A-Za-z0-9-]/g); + const pathBadChars = path.match(lbryuri.REGEXP_INVALID_URI); if (pathBadChars) { throw new Error( __(`Invalid character in path: %s`, pathBadChars.join(", "))