mirror of
https://github.com/LBRYFoundation/lbry-desktop.git
synced 2025-08-23 17:47:24 +00:00
Merge branch 'master' into ux-patch
This commit is contained in:
commit
5ed51109f6
15 changed files with 128 additions and 88 deletions
|
@ -1,5 +1,5 @@
|
||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 0.17.0rc1
|
current_version = 0.17.0
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)((?P<release>[a-z]+)(?P<candidate>\d+))?
|
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)((?P<release>[a-z]+)(?P<candidate>\d+))?
|
||||||
|
|
70
CHANGELOG.md
70
CHANGELOG.md
|
@ -8,43 +8,61 @@ Web UI version numbers should always match the corresponding version of LBRY App
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
* Added a new search service. Significantly improved search results.
|
*
|
||||||
* Channels now appear in search results. Channel cards to be improved soon?.
|
*
|
||||||
* Add setting to automatically purchase low-cost content without a confirmation dialog.
|
|
||||||
* New custom styled scrollbar (#574)
|
|
||||||
* New tabs (#547).
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
* LBRY protocol upgraded from v0.16.1 to [v0.17](https://github.com/lbryio/lbry/releases/tag/v0.17.0). Significant improvements to download performance anticipated.
|
*
|
||||||
* Improved Discover page load time by batching all URIs into one API call.
|
*
|
||||||
* Changed the File page to make it clearer how to to open the folder for a file.
|
|
||||||
* Display search bar on discover page instead of title and remove duplicated icon.
|
|
||||||
* Minor update for themes.
|
|
||||||
* There is no longer a minimum channel length (#645)
|
|
||||||
* Changed the File page to make it clearer how to to open the folder for a file
|
|
||||||
* The upgrade message is now friendlier and includes a link to the release notes.
|
|
||||||
* Local settings refactored and no longer intermixed with LBRY API library.
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* Improve layout (and implementation) of the icon panel in file tiles and cards
|
*
|
||||||
* The folder icon representing a local download now shows up properly on Channel pages (#587)
|
*
|
||||||
* While editing a publish, the URL will no longer change if you select a new file. (#601)
|
|
||||||
* Fixed issues with opening the folder for a file (#606)
|
|
||||||
* Be consistent with the step property on credit inputs (#604)
|
|
||||||
* Fixed unresponsive header (#613)
|
|
||||||
* Fixed dark theme issues with text content.
|
|
||||||
* Minor css fixes.
|
|
||||||
* Fixed issue when file fails to download (#642)
|
|
||||||
* Fixed issue after accessing a video without enough credits (#605)
|
|
||||||
* Fixed channel fetching without claims (#634)
|
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
*
|
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
|
||||||
|
## [0.17.0] - 2017-10-12
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Added a new search service. Significantly improved search results.
|
||||||
|
* Channels now appear in search results. Channel cards to be improved soon?.
|
||||||
|
* Add setting to automatically purchase low-cost content without a confirmation dialog.
|
||||||
|
* New custom styled scrollbar (#574)
|
||||||
|
* New tabs (#576).
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* LBRY protocol upgraded from v0.16.1 to [v0.17](https://github.com/lbryio/lbry/releases/tag/v0.17.0). Significant improvements to download performance anticipated.
|
||||||
|
* Improved Discover page load time by batching all URIs into one API call.
|
||||||
|
* Changed the File page to make it clearer how to to open the folder for a file.
|
||||||
|
* Display search bar on discover page instead of title and remove duplicated icon.
|
||||||
|
* Minor update for themes.
|
||||||
|
* There is no longer a minimum channel length (#645)
|
||||||
|
* Changed the File page to make it clearer how to to open the folder for a file
|
||||||
|
* The upgrade message is now friendlier and includes a link to the release notes.
|
||||||
|
* Local settings refactored and no longer intermixed with LBRY API library.
|
||||||
|
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Improve layout (and implementation) of the icon panel in file tiles and cards
|
||||||
|
* The folder icon representing a local download now shows up properly on Channel pages (#587)
|
||||||
|
* While editing a publish, the URL will no longer change if you select a new file. (#601)
|
||||||
|
* Fixed issues with opening the folder for a file (#606)
|
||||||
|
* Be consistent with the step property on credit inputs (#604)
|
||||||
|
* Fixed unresponsive header (#613)
|
||||||
|
* Fixed dark theme issues with text content.
|
||||||
|
* Minor css fixes.
|
||||||
|
* Fixed issue when file fails to download (#642)
|
||||||
|
* Fixed issue after accessing a video without enough credits (#605)
|
||||||
|
* Fixed channel fetching without claims (#634)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.16.0] - 2017-09-21
|
## [0.16.0] - 2017-09-21
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "LBRY",
|
"name": "LBRY",
|
||||||
"version": "0.17.0rc1",
|
"version": "0.17.0",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"description": "A browser for the LBRY network, a digital marketplace controlled by its users.",
|
"description": "A browser for the LBRY network, a digital marketplace controlled by its users.",
|
||||||
"author": {
|
"author": {
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
"electron-rebuild": "^1.5.11"
|
"electron-rebuild": "^1.5.11"
|
||||||
},
|
},
|
||||||
"lbrySettings": {
|
"lbrySettings": {
|
||||||
"lbrynetDaemonVersion": "0.17.0rc13",
|
"lbrynetDaemonVersion": "0.17.0",
|
||||||
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip"
|
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip"
|
||||||
},
|
},
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
|
|
|
@ -45,11 +45,17 @@ export function doResolveUris(uris) {
|
||||||
let resolveInfo = {};
|
let resolveInfo = {};
|
||||||
lbry.resolve({ uris: urisToResolve }).then(result => {
|
lbry.resolve({ uris: urisToResolve }).then(result => {
|
||||||
for (let [uri, uriResolveInfo] of Object.entries(result)) {
|
for (let [uri, uriResolveInfo] of Object.entries(result)) {
|
||||||
const { claim, certificate } = uriResolveInfo || {
|
const fallbackResolveInfo = {
|
||||||
claim: null,
|
claim: null,
|
||||||
|
claims_in_channel: null,
|
||||||
certificate: null,
|
certificate: null,
|
||||||
};
|
};
|
||||||
resolveInfo[uri] = { claim, certificate };
|
|
||||||
|
const { claim, certificate, claims_in_channel } = uriResolveInfo &&
|
||||||
|
!uriResolveInfo.error
|
||||||
|
? uriResolveInfo
|
||||||
|
: fallbackResolveInfo;
|
||||||
|
resolveInfo[uri] = { claim, certificate, claims_in_channel };
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -5,11 +5,13 @@ import { doNavigate } from "actions/navigation";
|
||||||
import { selectCurrentPage } from "selectors/navigation";
|
import { selectCurrentPage } from "selectors/navigation";
|
||||||
import batchActions from "util/batchActions";
|
import batchActions from "util/batchActions";
|
||||||
|
|
||||||
export function doSearch(query) {
|
export function doSearch(rawQuery) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const page = selectCurrentPage(state);
|
const page = selectCurrentPage(state);
|
||||||
|
|
||||||
|
const query = rawQuery.replace(/^lbry:\/\//, "");
|
||||||
|
|
||||||
if (!query) {
|
if (!query) {
|
||||||
return dispatch({
|
return dispatch({
|
||||||
type: types.SEARCH_CANCELLED,
|
type: types.SEARCH_CANCELLED,
|
||||||
|
|
|
@ -39,7 +39,7 @@ class App extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitleFromProps(props) {
|
setTitleFromProps(props) {
|
||||||
window.document.title = props.pageTitle;
|
window.document.title = props.pageTitle || "LBRY";
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { doFetchClaimCountByChannel } from "actions/content";
|
|
||||||
import { makeSelectClaimForUri } from "selectors/claims";
|
import { makeSelectClaimForUri } from "selectors/claims";
|
||||||
import { doNavigate } from "actions/navigation";
|
import { doNavigate } from "actions/navigation";
|
||||||
|
import { doResolveUri } from "actions/content";
|
||||||
import { makeSelectTotalItemsForChannel } from "selectors/content";
|
import { makeSelectTotalItemsForChannel } from "selectors/content";
|
||||||
|
import { makeSelectIsUriResolving } from "selectors/content";
|
||||||
import ChannelTile from "./view";
|
import ChannelTile from "./view";
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
|
isResolvingUri: makeSelectIsUriResolving(props.uri)(state),
|
||||||
totalItems: makeSelectTotalItemsForChannel(props.uri)(state),
|
totalItems: makeSelectTotalItemsForChannel(props.uri)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
fetchClaimCount: uri => dispatch(doFetchClaimCountByChannel(uri)),
|
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
||||||
|
resolveUri: uri => dispatch(doResolveUri(uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(ChannelTile);
|
export default connect(select, perform)(ChannelTile);
|
||||||
|
|
|
@ -1,27 +1,25 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import lbryuri from "lbryuri.js";
|
|
||||||
import CardMedia from "component/cardMedia";
|
import CardMedia from "component/cardMedia";
|
||||||
import { TruncatedText, BusyMessage } from "component/common.js";
|
import { TruncatedText, BusyMessage } from "component/common.js";
|
||||||
|
|
||||||
class ChannelTile extends React.PureComponent {
|
class ChannelTile extends React.PureComponent {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { uri, fetchClaimCount } = this.props;
|
const { uri, resolveUri } = this.props;
|
||||||
|
|
||||||
fetchClaimCount(uri);
|
resolveUri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const { uri, fetchClaimCount } = this.props;
|
const { uri, resolveUri } = this.props;
|
||||||
|
|
||||||
if (nextProps.uri != uri) {
|
if (nextProps.uri != uri) {
|
||||||
fetchClaimCount(uri);
|
resolveUri(uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { navigate, totalItems, uri } = this.props;
|
const { claim, navigate, isResolvingUri, totalItems, uri } = this.props;
|
||||||
const { name, claimId } = lbryuri.parse(uri);
|
|
||||||
|
|
||||||
let onClick = () => navigate("/show", { uri });
|
let onClick = () => navigate("/show", { uri });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -30,21 +28,22 @@ class ChannelTile extends React.PureComponent {
|
||||||
<div className={"card__inner file-tile__row"}>
|
<div className={"card__inner file-tile__row"}>
|
||||||
<CardMedia title={name} thumbnail={null} />
|
<CardMedia title={name} thumbnail={null} />
|
||||||
<div className="file-tile__content">
|
<div className="file-tile__content">
|
||||||
<div className="card__title-primary">
|
<div className="card__title-primary">
|
||||||
<h3>
|
<h3>
|
||||||
<TruncatedText lines={1}>{name}</TruncatedText>
|
<TruncatedText lines={1}>{uri}</TruncatedText>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content card__subtext">
|
<div className="card__content card__subtext">
|
||||||
{isNaN(totalItems) &&
|
{isResolvingUri &&
|
||||||
<BusyMessage message={__("Resolving channel")} />}
|
<BusyMessage message={__("Resolving channel")} />}
|
||||||
{totalItems > 0 &&
|
{totalItems > 0 &&
|
||||||
<span>
|
<span>
|
||||||
This is a channel with over {totalItems} items inside of it.
|
This is a channel with {totalItems}{" "}
|
||||||
</span>}
|
{totalItems === 1 ? " item" : " items"} inside of it.
|
||||||
{totalItems === 0 &&
|
</span>}
|
||||||
<span className="empty">This is an empty channel.</span>}
|
{!isResolvingUri &&
|
||||||
</div>
|
!totalItems &&
|
||||||
|
<span className="empty">This is an empty channel.</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -173,7 +173,7 @@ class PublishForm extends React.PureComponent {
|
||||||
topClaimValue() {
|
topClaimValue() {
|
||||||
if (!this.claim()) return null;
|
if (!this.claim()) return null;
|
||||||
|
|
||||||
return parseFloat(this.claim().amount);
|
return parseFloat(this.claim().effective_amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
myClaimExists() {
|
myClaimExists() {
|
||||||
|
|
|
@ -6,15 +6,17 @@ import FilePage from "page/file";
|
||||||
|
|
||||||
class ShowPage extends React.PureComponent {
|
class ShowPage extends React.PureComponent {
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const { resolveUri, uri } = this.props;
|
const { isResolvingUri, resolveUri, uri } = this.props;
|
||||||
|
|
||||||
resolveUri(uri);
|
if (!isResolvingUri) resolveUri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const { resolveUri, uri } = nextProps;
|
const { isResolvingUri, resolveUri, claim, uri } = nextProps;
|
||||||
|
|
||||||
resolveUri(uri);
|
if (!isResolvingUri && claim === undefined && uri) {
|
||||||
|
resolveUri(uri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -4,7 +4,7 @@ const reducers = {};
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
playingUri: null,
|
playingUri: null,
|
||||||
rewardedContentClaimIds: [],
|
rewardedContentClaimIds: [],
|
||||||
channelPages: {},
|
channelClaimCounts: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.FETCH_FEATURED_CONTENT_STARTED] = function(state, action) {
|
reducers[types.FETCH_FEATURED_CONTENT_STARTED] = function(state, action) {
|
||||||
|
@ -48,31 +48,38 @@ reducers[types.RESOLVE_URIS_STARTED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
reducers[types.RESOLVE_URIS_COMPLETED] = function(state, action) {
|
||||||
|
const { resolveInfo } = action.data;
|
||||||
|
const channelClaimCounts = Object.assign({}, state.channelClaimCounts);
|
||||||
|
|
||||||
|
for (let [uri, { certificate, claims_in_channel }] of Object.entries(
|
||||||
|
resolveInfo
|
||||||
|
)) {
|
||||||
|
if (certificate && !isNaN(claims_in_channel)) {
|
||||||
|
channelClaimCounts[uri] = claims_in_channel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
channelClaimCounts,
|
||||||
|
resolvingUris: (state.resolvingUris || []).filter(uri => !resolveInfo[uri]),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
reducers[types.SET_PLAYING_URI] = (state, action) => {
|
reducers[types.SET_PLAYING_URI] = (state, action) => {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
playingUri: action.data.uri,
|
playingUri: action.data.uri,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) {
|
|
||||||
// const channelPages = Object.assign({}, state.channelPages);
|
|
||||||
// const { uri, claims } = action.data;
|
|
||||||
//
|
|
||||||
// channelPages[uri] = totalPages;
|
|
||||||
//
|
|
||||||
// return Object.assign({}, state, {
|
|
||||||
// channelPages,
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
reducers[types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) {
|
reducers[types.FETCH_CHANNEL_CLAIM_COUNT_COMPLETED] = function(state, action) {
|
||||||
const channelPages = Object.assign({}, state.channelPages);
|
const channelClaimCounts = Object.assign({}, state.channelClaimCounts);
|
||||||
const { uri, totalClaims } = action.data;
|
const { uri, totalClaims } = action.data;
|
||||||
|
|
||||||
channelPages[uri] = Math.ceil(totalClaims / 10);
|
channelClaimCounts[uri] = totalClaims;
|
||||||
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
channelPages,
|
channelClaimCounts,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,20 +29,20 @@ export const makeSelectIsUriResolving = uri => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const selectChannelPages = createSelector(
|
export const selectChannelClaimCounts = createSelector(
|
||||||
_selectState,
|
_selectState,
|
||||||
state => state.channelPages || {}
|
state => state.channelClaimCounts || {}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const makeSelectTotalItemsForChannel = uri => {
|
export const makeSelectTotalItemsForChannel = uri => {
|
||||||
return createSelector(
|
return createSelector(selectChannelClaimCounts, byUri => byUri && byUri[uri]);
|
||||||
selectChannelPages,
|
|
||||||
byUri => (byUri && byUri[uri]) * 10
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const makeSelectTotalPagesForChannel = uri => {
|
export const makeSelectTotalPagesForChannel = uri => {
|
||||||
return createSelector(selectChannelPages, byUri => byUri && byUri[uri]);
|
return createSelector(
|
||||||
|
selectChannelClaimCounts,
|
||||||
|
byUri => byUri && byUri[uri] && Math.ceil(byUri[uri] / 10)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const selectRewardContentClaimIds = createSelector(
|
export const selectRewardContentClaimIds = createSelector(
|
||||||
|
|
|
@ -24,7 +24,11 @@ export const selectSearchUrisByQuery = createSelector(
|
||||||
);
|
);
|
||||||
|
|
||||||
export const makeSelectSearchUris = query => {
|
export const makeSelectSearchUris = query => {
|
||||||
return createSelector(selectSearchUrisByQuery, byQuery => byQuery[query]);
|
//replace statement below is kind of ugly, and repeated in doSearch action
|
||||||
|
return createSelector(
|
||||||
|
selectSearchUrisByQuery,
|
||||||
|
byQuery => byQuery[query ? query.replace(/^lbry:\/\//, "") : query]
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const selectWunderBarAddress = createSelector(
|
export const selectWunderBarAddress = createSelector(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "lbry-web-ui",
|
"name": "lbry-web-ui",
|
||||||
"version": "0.17.0rc1",
|
"version": "0.17.0",
|
||||||
"description": "LBRY UI",
|
"description": "LBRY UI",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
|
|
@ -129,7 +129,7 @@ input[readonly]:focus {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-field__label {
|
.form-field__label, .form-row__label {
|
||||||
color: var(--color-help);
|
color: var(--color-help);
|
||||||
&[for] { cursor: pointer; }
|
&[for] { cursor: pointer; }
|
||||||
> input[type="checkbox"], input[type="radio"] {
|
> input[type="checkbox"], input[type="radio"] {
|
||||||
|
|
Loading…
Add table
Reference in a new issue