From 91d4dd610e6766e2f6edc361301031b9830ae156 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Fri, 6 Oct 2017 17:46:41 -0400 Subject: [PATCH 1/2] search working, but no rendering of channels --- CHANGELOG.md | 2 + ui/js/actions/search.js | 50 +++++++++------ ui/js/component/fileListSearch/index.js | 13 +--- ui/js/component/fileListSearch/view.jsx | 47 +++----------- ui/js/component/fileTile/view.jsx | 2 - ui/js/lighthouse.js | 82 ------------------------- ui/js/main.js | 1 - ui/js/page/search/index.js | 6 +- ui/js/page/search/view.jsx | 1 - ui/js/reducers/search.js | 15 ++--- ui/js/selectors/search.js | 17 ++--- 11 files changed, 56 insertions(+), 180 deletions(-) delete mode 100644 ui/js/lighthouse.js diff --git a/CHANGELOG.md b/CHANGELOG.md index c179bc4b3..abb7480d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ Web UI version numbers should always match the corresponding version of LBRY App * 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 diff --git a/ui/js/actions/search.js b/ui/js/actions/search.js index 2d6be08ee..a83ce60bb 100644 --- a/ui/js/actions/search.js +++ b/ui/js/actions/search.js @@ -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)); - }); } }; } diff --git a/ui/js/component/fileListSearch/index.js b/ui/js/component/fileListSearch/index.js index bdb88faab..6d70fe190 100644 --- a/ui/js/component/fileListSearch/index.js +++ b/ui/js/component/fileListSearch/index.js @@ -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)), }); diff --git a/ui/js/component/fileListSearch/view.jsx b/ui/js/component/fileListSearch/view.jsx index 59884da8e..509608a90 100644 --- a/ui/js/component/fileListSearch/view.jsx +++ b/ui/js/component/fileListSearch/view.jsx @@ -1,52 +1,21 @@ 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 Link from "component/link"; -import { ToolTip } from "component/tooltip.js"; import { BusyMessage } from "component/common.js"; const SearchNoResults = props => { - const { navigate, query } = props; + const { query } = props; return (
{(__("No one has checked anything in for %s yet."), query)} {" "} - navigate("/publish")} /> +
); }; -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(); - } - return
{rows}
; -}; - class FileListSearch extends React.PureComponent { componentWillMount() { this.doSearch(this.props); @@ -63,21 +32,21 @@ class FileListSearch extends React.PureComponent { } render() { - const { isSearching, results } = this.props; + const { isSearching, uris, query } = this.props; return (
{isSearching && - !results && + !uris && } {isSearching && - results && + uris && } - {results && !!results.length - ? - : !isSearching && } + {uris && uris.length + ? uris.map(uri => ) + : !isSearching && }
); } diff --git a/ui/js/component/fileTile/view.jsx b/ui/js/component/fileTile/view.jsx index b243ea1d6..f5e682676 100644 --- a/ui/js/component/fileTile/view.jsx +++ b/ui/js/component/fileTile/view.jsx @@ -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"; diff --git a/ui/js/lighthouse.js b/ui/js/lighthouse.js deleted file mode 100644 index 32b748114..000000000 --- a/ui/js/lighthouse.js +++ /dev/null @@ -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; diff --git a/ui/js/main.js b/ui/js/main.js index 9c6059366..de18d0ee1 100644 --- a/ui/js/main.js +++ b/ui/js/main.js @@ -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"; diff --git a/ui/js/page/search/index.js b/ui/js/page/search/index.js index a6c571882..8426f3637 100644 --- a/ui/js/page/search/index.js +++ b/ui/js/page/search/index.js @@ -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"; diff --git a/ui/js/page/search/view.jsx b/ui/js/page/search/view.jsx index 0843b6141..e2ca65da2 100644 --- a/ui/js/page/search/view.jsx +++ b/ui/js/page/search/view.jsx @@ -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() { diff --git a/ui/js/reducers/search.js b/ui/js/reducers/search.js index ed500b987..c44c78cd2 100644 --- a/ui/js/reducers/search.js +++ b/ui/js/reducers/search.js @@ -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 }), }); }; diff --git a/ui/js/selectors/search.js b/ui/js/selectors/search.js index 9b967d66e..b817702a7 100644 --- a/ui/js/selectors/search.js +++ b/ui/js/selectors/search.js @@ -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, From 401bb85272bcbebc2861a65e294ae3e97fd94c6c Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Mon, 9 Oct 2017 19:19:50 -0400 Subject: [PATCH 2/2] shit-tier channel search results --- ui/js/component/channelTile/index.js | 19 ++++++++++ ui/js/component/channelTile/view.jsx | 50 +++++++++++++++++++++++++ ui/js/component/fileListSearch/view.jsx | 9 ++++- ui/js/modal/modalUpgrade/view.jsx | 2 +- ui/js/selectors/content.js | 7 ++++ 5 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 ui/js/component/channelTile/index.js create mode 100644 ui/js/component/channelTile/view.jsx diff --git a/ui/js/component/channelTile/index.js b/ui/js/component/channelTile/index.js new file mode 100644 index 000000000..2e4c438f7 --- /dev/null +++ b/ui/js/component/channelTile/index.js @@ -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); diff --git a/ui/js/component/channelTile/view.jsx b/ui/js/component/channelTile/view.jsx new file mode 100644 index 000000000..973d1dff5 --- /dev/null +++ b/ui/js/component/channelTile/view.jsx @@ -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 ( +
+
+
+
+

+ {uri} +

+
+
+ {isNaN(totalItems) && + } + {totalItems > 0 && + + This is a channel with over {totalItems} items inside of it. + } + {totalItems === 0 && + This is an empty channel.} +
+
+
+
+ ); + } +} + +export default ChannelTile; diff --git a/ui/js/component/fileListSearch/view.jsx b/ui/js/component/fileListSearch/view.jsx index 509608a90..224c48d6a 100644 --- a/ui/js/component/fileListSearch/view.jsx +++ b/ui/js/component/fileListSearch/view.jsx @@ -1,7 +1,9 @@ import React from "react"; import FileTile from "component/fileTile"; +import ChannelTile from "component/channelTile"; import Link from "component/link"; import { BusyMessage } from "component/common.js"; +import lbryuri from "lbryuri"; const SearchNoResults = props => { const { query } = props; @@ -45,7 +47,12 @@ class FileListSearch extends React.PureComponent { } {uris && uris.length - ? uris.map(uri => ) + ? uris.map( + uri => + lbryuri.parse(uri).name[0] === "@" + ? + : + ) : !isSearching && } ); diff --git a/ui/js/modal/modalUpgrade/view.jsx b/ui/js/modal/modalUpgrade/view.jsx index a02789331..7d10d9a0f 100644 --- a/ui/js/modal/modalUpgrade/view.jsx +++ b/ui/js/modal/modalUpgrade/view.jsx @@ -16,7 +16,7 @@ class ModalUpgrade extends React.PureComponent { onConfirmed={downloadUpgrade} onAborted={skipUpgrade} > -

{__("LBRY Just Got BTTR")}

+

{__("LBRY Leveled Up")}


{__("An updated version of LBRY is now available.")} diff --git a/ui/js/selectors/content.js b/ui/js/selectors/content.js index 0818134de..8e083ca93 100644 --- a/ui/js/selectors/content.js +++ b/ui/js/selectors/content.js @@ -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]); };