Merge branch 'lighthouse_v2'
This commit is contained in:
commit
dd667e8bad
15 changed files with 139 additions and 181 deletions
|
@ -22,6 +22,7 @@ Web UI version numbers should always match the corresponding version of LBRY App
|
|||
* 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.
|
||||
* Improved Discover page load time by batching all URIs into one API call
|
||||
* 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
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as types from "constants/action_types";
|
||||
import lbryuri from "lbryuri";
|
||||
import lighthouse from "lighthouse";
|
||||
import { doResolveUri } from "actions/content";
|
||||
import { doNavigate } from "actions/navigation";
|
||||
import { selectCurrentPage } from "selectors/navigation";
|
||||
|
@ -25,28 +24,41 @@ export function doSearch(query) {
|
|||
if (page != "search") {
|
||||
dispatch(doNavigate("search", { query: query }));
|
||||
} else {
|
||||
lighthouse.search(query).then(results => {
|
||||
const actions = [];
|
||||
fetch("https://lighthouse.lbry.io/search?s=" + query)
|
||||
.then(response => {
|
||||
return response.status === 200
|
||||
? Promise.resolve(response.json())
|
||||
: Promise.reject(new Error(response.statusText));
|
||||
})
|
||||
.then(data => {
|
||||
console.log(data);
|
||||
let uris = [];
|
||||
let actions = [];
|
||||
|
||||
results.forEach(result => {
|
||||
const uri = lbryuri.build({
|
||||
channelName: result.channel_name,
|
||||
contentName: result.name,
|
||||
claimId: result.channel_id || result.claim_id,
|
||||
data.forEach(result => {
|
||||
const uri = lbryuri.build({
|
||||
name: result.name,
|
||||
claimId: result.claimId,
|
||||
});
|
||||
actions.push(doResolveUri(uri));
|
||||
uris.push(uri);
|
||||
});
|
||||
actions.push(doResolveUri(uri));
|
||||
});
|
||||
|
||||
actions.push({
|
||||
type: types.SEARCH_COMPLETED,
|
||||
data: {
|
||||
query,
|
||||
results,
|
||||
},
|
||||
actions.push({
|
||||
type: types.SEARCH_COMPLETED,
|
||||
data: {
|
||||
query,
|
||||
uris,
|
||||
},
|
||||
});
|
||||
dispatch(batchActions(...actions));
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
dispatch({
|
||||
type: types.SEARCH_CANCELLED,
|
||||
});
|
||||
});
|
||||
|
||||
dispatch(batchActions(...actions));
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
19
ui/js/component/channelTile/index.js
Normal file
19
ui/js/component/channelTile/index.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { doFetchClaimCountByChannel } from "actions/content";
|
||||
import { makeSelectClaimForUri } from "selectors/claims";
|
||||
import { doNavigate } from "actions/navigation";
|
||||
import { makeSelectTotalItemsForChannel } from "selectors/content";
|
||||
import ChannelTile from "./view";
|
||||
|
||||
const select = (state, props) => ({
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
totalItems: makeSelectTotalItemsForChannel(props.uri)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
fetchClaimCount: uri => dispatch(doFetchClaimCountByChannel(uri)),
|
||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(ChannelTile);
|
50
ui/js/component/channelTile/view.jsx
Normal file
50
ui/js/component/channelTile/view.jsx
Normal file
|
@ -0,0 +1,50 @@
|
|||
import React from "react";
|
||||
import { TruncatedText, BusyMessage } from "component/common.js";
|
||||
|
||||
class ChannelTile extends React.PureComponent {
|
||||
componentDidMount() {
|
||||
const { uri, fetchClaimCount } = this.props;
|
||||
|
||||
fetchClaimCount(uri);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { uri, fetchClaimCount } = this.props;
|
||||
|
||||
if (nextProps.uri != uri) {
|
||||
fetchClaimCount(uri);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { navigate, totalItems, uri } = this.props;
|
||||
|
||||
let onClick = () => navigate("/show", { uri });
|
||||
|
||||
return (
|
||||
<section className="file-tile card">
|
||||
<div onClick={onClick} className="card__link">
|
||||
<div className="file-tile__content">
|
||||
<div className="card__title-primary">
|
||||
<h3>
|
||||
<TruncatedText lines={1}>{uri}</TruncatedText>
|
||||
</h3>
|
||||
</div>
|
||||
<div className="card__content card__subtext">
|
||||
{isNaN(totalItems) &&
|
||||
<BusyMessage message={__("Resolving channel")} />}
|
||||
{totalItems > 0 &&
|
||||
<span>
|
||||
This is a channel with over {totalItems} items inside of it.
|
||||
</span>}
|
||||
{totalItems === 0 &&
|
||||
<span className="empty">This is an empty channel.</span>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ChannelTile;
|
|
@ -1,22 +1,15 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { doSearch } from "actions/search";
|
||||
import {
|
||||
selectIsSearching,
|
||||
selectCurrentSearchResults,
|
||||
selectSearchQuery,
|
||||
} from "selectors/search";
|
||||
import { doNavigate } from "actions/navigation";
|
||||
import { selectIsSearching, makeSelectSearchUris } from "selectors/search";
|
||||
import FileListSearch from "./view";
|
||||
|
||||
const select = state => ({
|
||||
const select = (state, props) => ({
|
||||
isSearching: selectIsSearching(state),
|
||||
query: selectSearchQuery(state),
|
||||
results: selectCurrentSearchResults(state),
|
||||
uris: makeSelectSearchUris(props.query)(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
navigate: path => dispatch(doNavigate(path)),
|
||||
search: search => dispatch(doSearch(search)),
|
||||
});
|
||||
|
||||
|
|
|
@ -1,52 +1,23 @@
|
|||
import React from "react";
|
||||
import lbry from "lbry";
|
||||
import lbryio from "lbryio";
|
||||
import lbryuri from "lbryuri";
|
||||
import lighthouse from "lighthouse";
|
||||
import FileTile from "component/fileTile";
|
||||
import ChannelTile from "component/channelTile";
|
||||
import Link from "component/link";
|
||||
import { ToolTip } from "component/tooltip.js";
|
||||
import { BusyMessage } from "component/common.js";
|
||||
import lbryuri from "lbryuri";
|
||||
|
||||
const SearchNoResults = props => {
|
||||
const { navigate, query } = props;
|
||||
const { query } = props;
|
||||
|
||||
return (
|
||||
<section>
|
||||
<span className="empty">
|
||||
{(__("No one has checked anything in for %s yet."), query)} {" "}
|
||||
<Link label={__("Be the first")} onClick={() => navigate("/publish")} />
|
||||
<Link label={__("Be the first")} navigate="/publish" />
|
||||
</span>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
const FileListSearchResults = props => {
|
||||
const { results } = props;
|
||||
|
||||
const rows = [],
|
||||
seenNames = {}; //fix this when the search API returns claim IDs
|
||||
|
||||
for (let {
|
||||
name,
|
||||
claim,
|
||||
claim_id,
|
||||
channel_name,
|
||||
channel_id,
|
||||
txid,
|
||||
nout,
|
||||
} of results) {
|
||||
const uri = lbryuri.build({
|
||||
channelName: channel_name,
|
||||
contentName: name,
|
||||
claimId: channel_id || claim_id,
|
||||
});
|
||||
|
||||
rows.push(<FileTile key={uri} uri={uri} />);
|
||||
}
|
||||
return <div>{rows}</div>;
|
||||
};
|
||||
|
||||
class FileListSearch extends React.PureComponent {
|
||||
componentWillMount() {
|
||||
this.doSearch(this.props);
|
||||
|
@ -63,21 +34,26 @@ class FileListSearch extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { isSearching, results } = this.props;
|
||||
const { isSearching, uris, query } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{isSearching &&
|
||||
!results &&
|
||||
!uris &&
|
||||
<BusyMessage message={__("Looking up the Dewey Decimals")} />}
|
||||
|
||||
{isSearching &&
|
||||
results &&
|
||||
uris &&
|
||||
<BusyMessage message={__("Refreshing the Dewey Decimals")} />}
|
||||
|
||||
{results && !!results.length
|
||||
? <FileListSearchResults {...this.props} />
|
||||
: !isSearching && <SearchNoResults {...this.props} />}
|
||||
{uris && uris.length
|
||||
? uris.map(
|
||||
uri =>
|
||||
lbryuri.parse(uri).name[0] === "@"
|
||||
? <ChannelTile key={uri} uri={uri} />
|
||||
: <FileTile key={uri} uri={uri} />
|
||||
)
|
||||
: !isSearching && <SearchNoResults query={query} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ import React from "react";
|
|||
import * as icons from "constants/icons";
|
||||
import lbryuri from "lbryuri.js";
|
||||
import CardMedia from "component/cardMedia";
|
||||
import FileActions from "component/fileActions";
|
||||
import Link from "component/link";
|
||||
import { TruncatedText } from "component/common.js";
|
||||
import FilePrice from "component/filePrice";
|
||||
import NsfwOverlay from "component/nsfwOverlay";
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
import lbry from "./lbry.js";
|
||||
import jsonrpc from "./jsonrpc.js";
|
||||
|
||||
const queryTimeout = 3000;
|
||||
const maxQueryTries = 2;
|
||||
const defaultServers = [
|
||||
"http://lighthouse7.lbry.io:50005",
|
||||
"http://lighthouse8.lbry.io:50005",
|
||||
"http://lighthouse9.lbry.io:50005",
|
||||
];
|
||||
const path = "/";
|
||||
|
||||
let server = null;
|
||||
let connectTryNum = 0;
|
||||
|
||||
function getServers() {
|
||||
return defaultServers;
|
||||
}
|
||||
|
||||
function call(method, params, callback, errorCallback) {
|
||||
if (connectTryNum >= maxQueryTries) {
|
||||
errorCallback(
|
||||
new Error(
|
||||
__(
|
||||
`Could not connect to Lighthouse server. Last server attempted: %s`,
|
||||
server
|
||||
)
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Lighthouse server if it hasn't been set yet, if the current server is not in current
|
||||
* set of servers (most likely because of a settings change), or we're re-trying after a failed
|
||||
* query.
|
||||
*/
|
||||
if (!server || !getServers().includes(server) || connectTryNum > 0) {
|
||||
// If there's a current server, filter it out so we get a new one
|
||||
const newServerChoices = server
|
||||
? getServers().filter(s => s != server)
|
||||
: getServers();
|
||||
server =
|
||||
newServerChoices[
|
||||
Math.round(Math.random() * (newServerChoices.length - 1))
|
||||
];
|
||||
}
|
||||
|
||||
jsonrpc.call(
|
||||
server + path,
|
||||
method,
|
||||
params,
|
||||
response => {
|
||||
connectTryNum = 0;
|
||||
callback(response);
|
||||
},
|
||||
error => {
|
||||
connectTryNum = 0;
|
||||
errorCallback(error);
|
||||
},
|
||||
() => {
|
||||
connectTryNum++;
|
||||
call(method, params, callback, errorCallback);
|
||||
},
|
||||
queryTimeout
|
||||
);
|
||||
}
|
||||
|
||||
const lighthouse = new Proxy(
|
||||
{},
|
||||
{
|
||||
get: function(target, name) {
|
||||
return function(...params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
call(name, params, resolve, reject);
|
||||
});
|
||||
};
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export default lighthouse;
|
|
@ -1,6 +1,5 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import lbry from "./lbry.js";
|
||||
import App from "component/app/index.js";
|
||||
import SnackBar from "component/snackBar";
|
||||
import { Provider } from "react-redux";
|
||||
|
|
|
@ -16,7 +16,7 @@ class ModalUpgrade extends React.PureComponent {
|
|||
onConfirmed={downloadUpgrade}
|
||||
onAborted={skipUpgrade}
|
||||
>
|
||||
<h3 className="text-center">{__("LBRY Just Got BTTR")}</h3>
|
||||
<h3 className="text-center">{__("LBRY Leveled Up")}</h3>
|
||||
<br />
|
||||
<p>
|
||||
{__("An updated version of LBRY is now available.")}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import {
|
||||
selectIsSearching,
|
||||
selectSearchQuery,
|
||||
selectCurrentSearchResults,
|
||||
} from "selectors/search";
|
||||
import { selectIsSearching, selectSearchQuery } from "selectors/search";
|
||||
import { doNavigate } from "actions/navigation";
|
||||
import SearchPage from "./view";
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ import lbryuri from "lbryuri";
|
|||
import FileTile from "component/fileTile";
|
||||
import FileListSearch from "component/fileListSearch";
|
||||
import { ToolTip } from "component/tooltip.js";
|
||||
import { BusyMessage } from "component/common.js";
|
||||
|
||||
class SearchPage extends React.PureComponent {
|
||||
render() {
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import * as types from "constants/action_types";
|
||||
|
||||
const reducers = {};
|
||||
const defaultState = {};
|
||||
const defaultState = {
|
||||
urisByQuery: {},
|
||||
searching: false,
|
||||
};
|
||||
|
||||
reducers[types.SEARCH_STARTED] = function(state, action) {
|
||||
const { query } = action.data;
|
||||
|
@ -12,17 +15,11 @@ reducers[types.SEARCH_STARTED] = function(state, action) {
|
|||
};
|
||||
|
||||
reducers[types.SEARCH_COMPLETED] = function(state, action) {
|
||||
const { query, results } = action.data;
|
||||
const oldResults = Object.assign({}, state.results);
|
||||
const newByQuery = Object.assign({}, oldResults.byQuery);
|
||||
newByQuery[query] = results;
|
||||
const newResults = Object.assign({}, oldResults, {
|
||||
byQuery: newByQuery,
|
||||
});
|
||||
const { query, uris } = action.data;
|
||||
|
||||
return Object.assign({}, state, {
|
||||
searching: false,
|
||||
results: newResults,
|
||||
urisByQuery: Object.assign({}, state.urisByQuery, { [query]: uris }),
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -34,6 +34,13 @@ export const selectChannelPages = createSelector(
|
|||
state => state.channelPages || {}
|
||||
);
|
||||
|
||||
export const makeSelectTotalItemsForChannel = uri => {
|
||||
return createSelector(
|
||||
selectChannelPages,
|
||||
byUri => (byUri && byUri[uri]) * 10
|
||||
);
|
||||
};
|
||||
|
||||
export const makeSelectTotalPagesForChannel = uri => {
|
||||
return createSelector(selectChannelPages, byUri => byUri && byUri[uri]);
|
||||
};
|
||||
|
|
|
@ -18,21 +18,14 @@ export const selectIsSearching = createSelector(
|
|||
state => !!state.searching
|
||||
);
|
||||
|
||||
export const selectSearchResults = createSelector(
|
||||
export const selectSearchUrisByQuery = createSelector(
|
||||
_selectState,
|
||||
state => state.results || {}
|
||||
state => state.urisByQuery
|
||||
);
|
||||
|
||||
export const selectSearchResultsByQuery = createSelector(
|
||||
selectSearchResults,
|
||||
results => results.byQuery || {}
|
||||
);
|
||||
|
||||
export const selectCurrentSearchResults = createSelector(
|
||||
selectSearchQuery,
|
||||
selectSearchResultsByQuery,
|
||||
(query, byQuery) => byQuery[query]
|
||||
);
|
||||
export const makeSelectSearchUris = query => {
|
||||
return createSelector(selectSearchUrisByQuery, byQuery => byQuery[query]);
|
||||
};
|
||||
|
||||
export const selectWunderBarAddress = createSelector(
|
||||
selectCurrentPage,
|
||||
|
|
Loading…
Add table
Reference in a new issue