Merge remote-tracking branch 'origin/master' into rewards3
This commit is contained in:
commit
ac34faea80
15 changed files with 94 additions and 37 deletions
|
@ -13,6 +13,7 @@ Web UI version numbers should always match the corresponding version of LBRY App
|
||||||
* Support markdown makeup in claim description
|
* Support markdown makeup in claim description
|
||||||
* Replaced free speech flag (used when image is missing) with labeled color tiles
|
* Replaced free speech flag (used when image is missing) with labeled color tiles
|
||||||
* Added a loading message to file actions
|
* Added a loading message to file actions
|
||||||
|
* URL is auto suggested in Publish Page
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
* Publishes now uses claims rather than files
|
* Publishes now uses claims rather than files
|
||||||
|
@ -28,6 +29,11 @@ Web UI version numbers should always match the corresponding version of LBRY App
|
||||||
* Restored feedback on claim amounts
|
* Restored feedback on claim amounts
|
||||||
* Fixed hiding price input when Free is checked on publish form
|
* Fixed hiding price input when Free is checked on publish form
|
||||||
* Fixed hiding new identity fields 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
|
||||||
|
* Fixed refresh regression after adding scroll position to history state
|
||||||
|
* Fixed app thinking downloads with 0 progress were downloaded after restart
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
*
|
*
|
||||||
|
|
|
@ -46,8 +46,8 @@ dir dist # verify that binary was built/named correctly
|
||||||
|
|
||||||
# sign binary
|
# sign binary
|
||||||
nuget install secure-file -ExcludeVersion
|
nuget install secure-file -ExcludeVersion
|
||||||
secure-file\tools\secure-file -decrypt build\lbry2.pfx.enc -secret "$env:pfx_key"
|
secure-file\tools\secure-file -decrypt build\lbry3.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
|
& ${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
|
python build\upload_assets.py
|
||||||
|
|
Binary file not shown.
BIN
build/lbry3.pfx.enc
Normal file
BIN
build/lbry3.pfx.enc
Normal file
Binary file not shown.
|
@ -13,6 +13,7 @@ import { doFetchDaemonSettings } from "actions/settings";
|
||||||
import { doAuthenticate } from "actions/user";
|
import { doAuthenticate } from "actions/user";
|
||||||
import { doFileList } from "actions/file_info";
|
import { doFileList } from "actions/file_info";
|
||||||
import { toQueryString } from "util/query_params";
|
import { toQueryString } from "util/query_params";
|
||||||
|
import { parseQueryParams } from "util/query_params";
|
||||||
|
|
||||||
const { remote, ipcRenderer, shell } = require("electron");
|
const { remote, ipcRenderer, shell } = require("electron");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
@ -76,6 +77,7 @@ export function doChangePath(path, options = {}) {
|
||||||
export function doHistoryBack() {
|
export function doHistoryBack() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
if (!history.state) return;
|
if (!history.state) return;
|
||||||
|
if (history.state.index === 0) return;
|
||||||
|
|
||||||
history.back();
|
history.back();
|
||||||
};
|
};
|
||||||
|
@ -260,7 +262,9 @@ export function doAlertError(errorList) {
|
||||||
|
|
||||||
export function doDaemonReady() {
|
export function doDaemonReady() {
|
||||||
return function(dispatch, getState) {
|
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(doAuthenticate());
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.DAEMON_READY,
|
type: types.DAEMON_READY,
|
||||||
|
|
|
@ -5,7 +5,7 @@ import lbryuri from "lbryuri";
|
||||||
import { selectBalance } from "selectors/wallet";
|
import { selectBalance } from "selectors/wallet";
|
||||||
import {
|
import {
|
||||||
selectFileInfoForUri,
|
selectFileInfoForUri,
|
||||||
selectUrisDownloading,
|
selectDownloadingByOutpoint,
|
||||||
} from "selectors/file_info";
|
} from "selectors/file_info";
|
||||||
import { selectResolvingUris } from "selectors/content";
|
import { selectResolvingUris } from "selectors/content";
|
||||||
import { selectCostInfoForUri } from "selectors/cost_info";
|
import { selectCostInfoForUri } from "selectors/cost_info";
|
||||||
|
@ -265,8 +265,9 @@ export function doPurchaseUri(uri, purchaseModalName) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const balance = selectBalance(state);
|
const balance = selectBalance(state);
|
||||||
const fileInfo = selectFileInfoForUri(state, { uri });
|
const fileInfo = selectFileInfoForUri(state, { uri });
|
||||||
const downloadingByUri = selectUrisDownloading(state);
|
const downloadingByOutpoint = selectDownloadingByOutpoint(state);
|
||||||
const alreadyDownloading = !!downloadingByUri[uri];
|
const alreadyDownloading =
|
||||||
|
fileInfo && !!downloadingByOutpoint[fileInfo.outpoint];
|
||||||
|
|
||||||
// we already fully downloaded the file.
|
// we already fully downloaded the file.
|
||||||
if (fileInfo && fileInfo.completed) {
|
if (fileInfo && fileInfo.completed) {
|
||||||
|
|
|
@ -10,8 +10,11 @@ import {
|
||||||
selectIsFetchingFileList,
|
selectIsFetchingFileList,
|
||||||
selectFileInfosByOutpoint,
|
selectFileInfosByOutpoint,
|
||||||
selectUrisLoading,
|
selectUrisLoading,
|
||||||
|
selectTotalDownloadProgress,
|
||||||
} from "selectors/file_info";
|
} 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");
|
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));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,10 @@ class FileActions extends React.PureComponent {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (fileInfo === null && !downloading) {
|
} else if (
|
||||||
|
(fileInfo === null || (fileInfo && fileInfo.written_bytes === 0)) &&
|
||||||
|
!downloading
|
||||||
|
) {
|
||||||
if (!costInfo) {
|
if (!costInfo) {
|
||||||
content = <BusyMessage message={__("Fetching cost info")} />;
|
content = <BusyMessage message={__("Fetching cost info")} />;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { doCloseModal, doHistoryBack } from "actions/app";
|
import { doCloseModal, doHistoryBack } from "actions/app";
|
||||||
import { doDeleteFile } from "actions/file_info";
|
import { doDeleteFileAndGoBack } from "actions/file_info";
|
||||||
import { makeSelectClaimForUriIsMine } from "selectors/claims";
|
import { makeSelectClaimForUriIsMine } from "selectors/claims";
|
||||||
|
import batchActions from "util/batchActions";
|
||||||
|
|
||||||
import ModalRemoveFile from "./view";
|
import ModalRemoveFile from "./view";
|
||||||
|
|
||||||
|
@ -19,8 +20,7 @@ const makeSelect = () => {
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
closeModal: () => dispatch(doCloseModal()),
|
closeModal: () => dispatch(doCloseModal()),
|
||||||
deleteFile: (fileInfo, deleteFromComputer, abandonClaim) => {
|
deleteFile: (fileInfo, deleteFromComputer, abandonClaim) => {
|
||||||
dispatch(doHistoryBack());
|
dispatch(doDeleteFileAndGoBack(fileInfo, deleteFromComputer, abandonClaim));
|
||||||
dispatch(doDeleteFile(fileInfo, deleteFromComputer, abandonClaim));
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ class PublishForm extends React.PureComponent {
|
||||||
creatingChannel: false,
|
creatingChannel: false,
|
||||||
modal: null,
|
modal: null,
|
||||||
isFee: false,
|
isFee: false,
|
||||||
|
customUrl: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,6 +204,9 @@ class PublishForm extends React.PureComponent {
|
||||||
|
|
||||||
handleNameChange(event) {
|
handleNameChange(event) {
|
||||||
var rawName = event.target.value;
|
var rawName = event.target.value;
|
||||||
|
this.setState({
|
||||||
|
customUrl: Boolean(rawName.length),
|
||||||
|
});
|
||||||
|
|
||||||
this.nameChanged(rawName);
|
this.nameChanged(rawName);
|
||||||
}
|
}
|
||||||
|
@ -445,11 +449,24 @@ class PublishForm extends React.PureComponent {
|
||||||
onFileChange() {
|
onFileChange() {
|
||||||
if (this.refs.file.getValue()) {
|
if (this.refs.file.getValue()) {
|
||||||
this.setState({ hasFile: true });
|
this.setState({ hasFile: true });
|
||||||
|
if (!this.state.customUrl) {
|
||||||
|
let fileName = this._getFileName(this.refs.file.getValue());
|
||||||
|
this.nameChanged(fileName);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.setState({ hasFile: false });
|
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() {
|
getNameBidHelpText() {
|
||||||
if (this.state.prefillDone) {
|
if (this.state.prefillDone) {
|
||||||
return __("Existing claim data was prefilled");
|
return __("Existing claim data was prefilled");
|
||||||
|
|
|
@ -34,7 +34,6 @@ class UserEmailVerify extends React.PureComponent {
|
||||||
<FormRow
|
<FormRow
|
||||||
type="text"
|
type="text"
|
||||||
label={__("Verification Code")}
|
label={__("Verification Code")}
|
||||||
placeholder="a94bXXXXXXXXXXXXXX"
|
|
||||||
name="code"
|
name="code"
|
||||||
value={this.state.code}
|
value={this.state.code}
|
||||||
onChange={event => {
|
onChange={event => {
|
||||||
|
@ -45,7 +44,7 @@ class UserEmailVerify extends React.PureComponent {
|
||||||
{/* render help separately so it always shows */}
|
{/* render help separately so it always shows */}
|
||||||
<div className="form-field__helper">
|
<div className="form-field__helper">
|
||||||
<p>
|
<p>
|
||||||
{__("Email")}{" "}
|
{__("Check your email for a verification code. Email")}{" "}
|
||||||
<Link href="mailto:help@lbry.io" label="help@lbry.io" />{" "}
|
<Link href="mailto:help@lbry.io" label="help@lbry.io" />{" "}
|
||||||
{__("if you did not receive or are having trouble with your code.")}
|
{__("if you did not receive or are having trouble with your code.")}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -291,7 +291,7 @@ lbry.setClientSetting = function(setting, value) {
|
||||||
lbry.formatName = function(name) {
|
lbry.formatName = function(name) {
|
||||||
// Converts LBRY name to standard format (all lower case, no special characters, spaces replaced by dashes)
|
// Converts LBRY name to standard format (all lower case, no special characters, spaces replaced by dashes)
|
||||||
name = name.replace("/s+/g", "-");
|
name = name.replace("/s+/g", "-");
|
||||||
name = name.toLowerCase().replace(/[^a-z0-9\-]/g, "");
|
name = name.toLowerCase().replace(lbryuri.REGEXP_INVALID_URI, "");
|
||||||
return name;
|
return name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ const CLAIM_ID_MAX_LEN = 40;
|
||||||
|
|
||||||
const lbryuri = {};
|
const lbryuri = {};
|
||||||
|
|
||||||
|
lbryuri.REGEXP_INVALID_URI = /[^A-Za-z0-9-]/g;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a LBRY name into its component parts. Throws errors with user-friendly
|
* Parses a LBRY name into its component parts. Throws errors with user-friendly
|
||||||
* messages for invalid names.
|
* messages for invalid names.
|
||||||
|
@ -70,7 +72,7 @@ lbryuri.parse = function(uri, requireProto = false) {
|
||||||
contentName = path;
|
contentName = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nameBadChars = (channelName || name).match(/[^A-Za-z0-9-]/g);
|
const nameBadChars = (channelName || name).match(lbryuri.REGEXP_INVALID_URI);
|
||||||
if (nameBadChars) {
|
if (nameBadChars) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
__(
|
__(
|
||||||
|
@ -119,7 +121,7 @@ lbryuri.parse = function(uri, requireProto = false) {
|
||||||
throw new Error(__("Only channel URIs may have a path."));
|
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) {
|
if (pathBadChars) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
__(`Invalid character in path: %s`, pathBadChars.join(", "))
|
__(`Invalid character in path: %s`, pathBadChars.join(", "))
|
||||||
|
|
|
@ -58,15 +58,15 @@ reducers[types.DOWNLOADING_STARTED] = function(state, action) {
|
||||||
const { uri, outpoint, fileInfo } = action.data;
|
const { uri, outpoint, fileInfo } = action.data;
|
||||||
|
|
||||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||||
const newDownloading = Object.assign({}, state.urisDownloading);
|
const newDownloading = Object.assign({}, state.downloadingByOutpoin);
|
||||||
const newLoading = Object.assign({}, state.urisLoading);
|
const newLoading = Object.assign({}, state.urisLoading);
|
||||||
|
|
||||||
newDownloading[uri] = true;
|
newDownloading[outpoint] = true;
|
||||||
newByOutpoint[outpoint] = fileInfo;
|
newByOutpoint[outpoint] = fileInfo;
|
||||||
delete newLoading[uri];
|
delete newLoading[uri];
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
urisDownloading: newDownloading,
|
downloadingByOutpoint: newDownloading,
|
||||||
urisLoading: newLoading,
|
urisLoading: newLoading,
|
||||||
byOutpoint: newByOutpoint,
|
byOutpoint: newByOutpoint,
|
||||||
});
|
});
|
||||||
|
@ -76,14 +76,14 @@ reducers[types.DOWNLOADING_PROGRESSED] = function(state, action) {
|
||||||
const { uri, outpoint, fileInfo } = action.data;
|
const { uri, outpoint, fileInfo } = action.data;
|
||||||
|
|
||||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||||
const newDownloading = Object.assign({}, state.urisDownloading);
|
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
||||||
|
|
||||||
newByOutpoint[outpoint] = fileInfo;
|
newByOutpoint[outpoint] = fileInfo;
|
||||||
newDownloading[uri] = true;
|
newDownloading[outpoint] = true;
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
byOutpoint: newByOutpoint,
|
byOutpoint: newByOutpoint,
|
||||||
urisDownloading: newDownloading,
|
downloadingByOutpoint: newDownloading,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,14 +91,14 @@ reducers[types.DOWNLOADING_COMPLETED] = function(state, action) {
|
||||||
const { uri, outpoint, fileInfo } = action.data;
|
const { uri, outpoint, fileInfo } = action.data;
|
||||||
|
|
||||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||||
const newDownloading = Object.assign({}, state.urisDownloading);
|
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
||||||
|
|
||||||
newByOutpoint[outpoint] = fileInfo;
|
newByOutpoint[outpoint] = fileInfo;
|
||||||
delete newDownloading[uri];
|
delete newDownloading[outpoint];
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
byOutpoint: newByOutpoint,
|
byOutpoint: newByOutpoint,
|
||||||
urisDownloading: newDownloading,
|
downloadingByOutpoint: newDownloading,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,11 +106,14 @@ reducers[types.FILE_DELETE] = function(state, action) {
|
||||||
const { outpoint } = action.data;
|
const { outpoint } = action.data;
|
||||||
|
|
||||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||||
|
const downloadingByOutpoint = Object.assign({}, state.downloadingByOutpoint);
|
||||||
|
|
||||||
delete newByOutpoint[outpoint];
|
delete newByOutpoint[outpoint];
|
||||||
|
delete downloadingByOutpoint[outpoint];
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
byOutpoint: newByOutpoint,
|
byOutpoint: newByOutpoint,
|
||||||
|
downloadingByOutpoint,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -39,14 +39,18 @@ export const makeSelectFileInfoForUri = () => {
|
||||||
return createSelector(selectFileInfoForUri, fileInfo => fileInfo);
|
return createSelector(selectFileInfoForUri, fileInfo => fileInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const selectUrisDownloading = createSelector(
|
export const selectDownloadingByOutpoint = createSelector(
|
||||||
_selectState,
|
_selectState,
|
||||||
state => state.urisDownloading || {}
|
state => state.downloadingByOutpoint || {}
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectDownloadingForUri = (state, props) => {
|
const selectDownloadingForUri = (state, props) => {
|
||||||
const byUri = selectUrisDownloading(state);
|
const byOutpoint = selectDownloadingByOutpoint(state);
|
||||||
return byUri[props.uri];
|
const fileInfo = selectFileInfoForUri(state, props);
|
||||||
|
|
||||||
|
if (!fileInfo) return false;
|
||||||
|
|
||||||
|
return byOutpoint[fileInfo.outpoint];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const makeSelectDownloadingForUri = () => {
|
export const makeSelectDownloadingForUri = () => {
|
||||||
|
@ -135,14 +139,14 @@ export const selectFileInfosByUri = createSelector(
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectDownloadingFileInfos = createSelector(
|
export const selectDownloadingFileInfos = createSelector(
|
||||||
selectUrisDownloading,
|
selectDownloadingByOutpoint,
|
||||||
selectFileInfosByUri,
|
selectFileInfosByOutpoint,
|
||||||
(urisDownloading, byUri) => {
|
(downloadingByOutpoint, fileInfosByOutpoint) => {
|
||||||
const uris = Object.keys(urisDownloading);
|
const outpoints = Object.keys(downloadingByOutpoint);
|
||||||
const fileInfos = [];
|
const fileInfos = [];
|
||||||
|
|
||||||
uris.forEach(uri => {
|
outpoints.forEach(outpoint => {
|
||||||
const fileInfo = byUri[uri];
|
const fileInfo = fileInfosByOutpoint[outpoint];
|
||||||
|
|
||||||
if (fileInfo) fileInfos.push(fileInfo);
|
if (fileInfo) fileInfos.push(fileInfo);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue