From a2aaf65be5b2e1e54ea8b9b56ac384eb7f29df8d Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Thu, 29 Dec 2016 04:17:10 -0500 Subject: [PATCH 01/13] Add developer settings to lbry.js --- js/lbry.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/lbry.js b/js/lbry.js index ca9fde1e5..e7a7dbd7a 100644 --- a/js/lbry.js +++ b/js/lbry.js @@ -10,6 +10,9 @@ var lbry = { }, defaultClientSettings: { showNsfw: false, + debug: false, + useCustomLighthouseServers: false, + customLighthouseServers: [], } }; From f947164164edcbf3717b8b751df060b0a646fad1 Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Thu, 29 Dec 2016 04:23:28 -0500 Subject: [PATCH 02/13] Add Developer Settings page --- js/app.js | 3 +++ js/page/developer.js | 56 ++++++++++++++++++++++++++++++++++++++++++++ scss/_gui.scss | 7 ++++++ 3 files changed, 66 insertions(+) create mode 100644 js/page/developer.js diff --git a/js/app.js b/js/app.js index 6232b8461..dae0b8596 100644 --- a/js/app.js +++ b/js/app.js @@ -13,6 +13,7 @@ import DetailPage from './page/show.js'; import PublishPage from './page/publish.js'; import DiscoverPage from './page/discover.js'; import SplashScreen from './component/splash.js'; +import DeveloperPage from './page/developer.js'; import Drawer from './component/drawer.js'; import Header from './component/header.js'; import Modal from './component/modal.js'; @@ -191,6 +192,8 @@ var App = React.createClass({ return ; case 'publish': return ; + case 'developer': + return ; case 'discover': default: return ; diff --git a/js/page/developer.js b/js/page/developer.js new file mode 100644 index 000000000..447418191 --- /dev/null +++ b/js/page/developer.js @@ -0,0 +1,56 @@ +import lbry from '../lbry.js'; +import React from 'react'; +import FormField from '../component/form.js'; + +const DeveloperPage = React.createClass({ + getInitialState: function() { + return { + debugMode: lbry.getClientSetting('debug'), + useCustomLighthouseServers: lbry.getClientSetting('useCustomLighthouseServers'), + customLighthouseServers: lbry.getClientSetting('customLighthouseServers').join('\n'), + }; + }, + handleDebugModeChange: function(event) { + lbry.setClientSetting('debug', event.target.checked); + this.setState({ + debugMode: event.target.checked, + }); + }, + handleUseCustomLighthouseServersChange: function(event) { + lbry.setClientSetting('useCustomLighthouseServers', event.target.checked); + this.setState({ + useCustomLighthouseServers: event.target.checked, + }); + }, + handleCustomLighthouseServersChange: function(event) { + lbry.setClientSetting('customLighthouseServers', event.target.value.trim().split('\n')); + this.setState({ + customLighthouseServers: event.target.value, + }); + }, + render: function() { + return ( +
+
+

Developer Settings

+
+ +
+
+ +
+ {this.state.useCustomLighthouseServers + ?
+ +
+ : null} +
+
+ ); + } +}); + +export default DeveloperPage; diff --git a/scss/_gui.scss b/scss/_gui.scss index e533b8504..936f17ccb 100644 --- a/scss/_gui.scss +++ b/scss/_gui.scss @@ -365,4 +365,11 @@ input[type="text"], input[type="search"] .download-started-modal__file-path { word-break: break-all; +} + + +.developer-page__custom-lighthouse-servers { + font: 0.8em monospace; + width: 30em; + height: 10em; } \ No newline at end of file From 9e2b43c5317f356585bb12b6903ae4cd72070950 Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Thu, 29 Dec 2016 04:41:28 -0500 Subject: [PATCH 03/13] Implement debug mode Exposes lbry and lighthouse modules in global scope for easy testing. --- js/main.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/js/main.js b/js/main.js index 8ff6853a8..d39fc84a5 100644 --- a/js/main.js +++ b/js/main.js @@ -1,11 +1,17 @@ import React from 'react'; import ReactDOM from 'react-dom'; import lbry from './lbry.js'; +import lighthouse from './lighthouse.js'; import App from './app.js'; import SplashScreen from './component/splash.js'; var init = function() { + if (lbry.getClientSetting('debug')) { + window.lbry = lbry; + window.lighthouse = lighthouse; + } + var canvas = document.getElementById('canvas'); ReactDOM.render( From 5bcf09560073ed31700d64451b3c584badc9c2e4 Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Thu, 29 Dec 2016 04:57:07 -0500 Subject: [PATCH 04/13] Refactor lighthouse.js and add support for custom servers - Adds support for custom servers - Some light refactoring; mainly moving the logic for retrying queries into lbry.call() instead of leaving it up to the individual methods --- js/lighthouse.js | 57 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/js/lighthouse.js b/js/lighthouse.js index 0a5de3152..6d349a3a8 100644 --- a/js/lighthouse.js +++ b/js/lighthouse.js @@ -1,8 +1,8 @@ import lbry from './lbry.js'; var lighthouse = { - _search_timeout: 5000, - _max_search_tries: 5, + _query_timeout: 5000, + _max_query_tries: 5, servers: [ 'http://lighthouse4.lbry.io:50005', @@ -12,37 +12,56 @@ var lighthouse = { path: '/', call: function(method, params, callback, errorCallback, connectFailedCallback, timeout) { - lbry.jsonrpc_call(this.server + this.path, method, params, callback, errorCallback, connectFailedCallback, timeout); - }, - - search: function(query, callback, errorCallback, connectFailedCallback, timeout) { - let handleSearchFailed = function(tryNum=0) { - if (tryNum > lighthouse._max_search_tries) { + const handleConnectFailed = function(tryNum=0) { + if (tryNum > lighthouse._max_query_tries) { if (connectFailedCallback) { connectFailedCallback(); } else { throw new Error(`Could not connect to Lighthouse server. Last server attempted: ${lighthouse.server}`); } } else { - // Randomly choose one of the other search servers to switch to - let otherServers = lighthouse.servers.slice(); - otherServers.splice(otherServers.indexOf(lighthouse.server), 1); - lighthouse.server = otherServers[Math.round(Math.random() * (otherServers.length - 1))]; - - lighthouse.call('search', [query], callback, errorCallback, function() { - handleSearchFailed(tryNum + 1); - }, lighthouse._search_timeout); + lbry.call(method, params, callback, errorCallback, () => { handleConnectFailed(tryNum + 1) }, timeout); } } - lighthouse.call('search', [query], callback, errorCallback, function() { handleSearchFailed() }, lighthouse._search_timeout); + // Set the Lighthouse server if it hasn't been set yet, or if the current server is not in + // the current set of servers (most likely because of a settings change). + if (typeof lighthouse.server === 'undefined' || lighthouse.getServers().indexOf(lighthouse.server) == -1) { + lighthouse.chooseNewServer(); + } + + lbry.jsonrpc_call(this.server + this.path, method, params, callback, errorCallback, + () => { handleConnectFailed() }, timeout || lighthouse.query_timeout); + }, + + getServers: function() { + return lbry.getClientSetting('useCustomLighthouseServers') + ? lbry.getClientSetting('customLighthouseServers') + : lighthouse.servers; + }, + + chooseNewServer: function() { + // Randomly choose a new Lighthouse server and switch to it. If a server is already set, this + // will choose a different one (used for switching servers after a failed query). + const servers = lighthouse.getServers(); + let newServerChoices; + if (!lighthouse.server) { + newServerChoices = servers; + } else { + newServerChoices = lighthouse.getServers().slice(); + newServerChoices.splice(newServerChoices.indexOf(lighthouse.server), 1); + } + lighthouse.server = newServerChoices[Math.round(Math.random() * (newServerChoices.length - 1))]; + }, + + search: function(query, callback, errorCallback, connectFailedCallback, timeout) { + lighthouse.call('search', [query], callback, errorCallback, connectFailedCallback, timeout); }, getSizeForName: function(name, callback, errorCallback, connectFailedCallback, timeout) { - return lighthouse.call('get_size_for_name', [name], callback, errorCallback, connectFailedCallback, timeout); + lighthouse.call('get_size_for_name', [name], callback, errorCallback, connectFailedCallback, timeout); } }; -lighthouse.server = lighthouse.servers[Math.round(Math.random() * (lighthouse.servers.length - 1))]; export default lighthouse; From cc335cfc6583eddb956059fa286a4ee1224876c8 Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Fri, 30 Dec 2016 04:38:51 -0500 Subject: [PATCH 05/13] Move Developer Settings page styles to separate file --- scss/_gui.scss | 6 ------ scss/all.scss | 3 ++- scss/page/_developer.scss | 5 +++++ 3 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 scss/page/_developer.scss diff --git a/scss/_gui.scss b/scss/_gui.scss index 936f17ccb..965d2eb9e 100644 --- a/scss/_gui.scss +++ b/scss/_gui.scss @@ -367,9 +367,3 @@ input[type="text"], input[type="search"] word-break: break-all; } - -.developer-page__custom-lighthouse-servers { - font: 0.8em monospace; - width: 30em; - height: 10em; -} \ No newline at end of file diff --git a/scss/all.scss b/scss/all.scss index cbaf6d901..e02fd6d3d 100644 --- a/scss/all.scss +++ b/scss/all.scss @@ -4,4 +4,5 @@ @import "_mediaelement"; @import "_canvas"; @import "_table"; -@import "_gui"; \ No newline at end of file +@import "_gui"; +@import "page/_developer.scss"; \ No newline at end of file diff --git a/scss/page/_developer.scss b/scss/page/_developer.scss new file mode 100644 index 000000000..1a3a118d6 --- /dev/null +++ b/scss/page/_developer.scss @@ -0,0 +1,5 @@ +.developer-page__custom-lighthouse-servers { + font: 0.8em monospace; + width: 30em; + height: 10em; +} \ No newline at end of file From ed38e2ea758dfedfd6e07b4b87869820ac68faf0 Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Fri, 30 Dec 2016 07:40:07 -0500 Subject: [PATCH 06/13] Add import for BusyMessage to discover.js --- js/page/discover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/page/discover.js b/js/page/discover.js index 77633ca84..f551eed68 100644 --- a/js/page/discover.js +++ b/js/page/discover.js @@ -2,7 +2,7 @@ import React from 'react'; import lbry from '../lbry.js'; import lighthouse from '../lighthouse.js'; import {Link, ToolTipLink, DownloadLink, WatchLink} from '../component/link.js'; -import {Thumbnail, CreditAmount, TruncatedText} from '../component/common.js'; +import {Thumbnail, CreditAmount, TruncatedText, BusyMessage} from '../component/common.js'; var fetchResultsStyle = { color: '#888', From 7e86cccd6c4dd77a43ea8d41a1a608837bcbc62b Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Fri, 30 Dec 2016 07:42:47 -0500 Subject: [PATCH 07/13] Restore Dewey Decimals message The "no results found" message was showing instead due to some tricky state management stuff. --- js/app.js | 4 ++-- js/page/discover.js | 27 +++++++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/js/app.js b/js/app.js index 6232b8461..f13e00c4f 100644 --- a/js/app.js +++ b/js/app.js @@ -39,7 +39,7 @@ var App = React.createClass({ return { viewingPage: viewingPage, drawerOpen: drawerOpenRaw !== null ? JSON.parse(drawerOpenRaw) : true, - pageArgs: val, + pageArgs: typeof val !== 'undefined' ? val : null, errorInfo: null, modal: null, startNotice: null, @@ -193,7 +193,7 @@ var App = React.createClass({ return ; case 'discover': default: - return ; + return ; } }, render: function() { diff --git a/js/page/discover.js b/js/page/discover.js index f551eed68..acd126925 100644 --- a/js/page/discover.js +++ b/js/page/discover.js @@ -268,20 +268,27 @@ var DiscoverPage = React.createClass({ componentDidUpdate: function() { if (this.props.query != this.state.query) { - this.handleSearchChanged(); + this.handleSearchChanged(this.props.query); } }, - handleSearchChanged: function() { - this.setState({ - searching: true, - query: this.props.query, - }); - - lighthouse.search(this.props.query, this.searchCallback); + componentWillReceiveProps: function(nextProps, nextState) { + if (nextProps.query != nextState.query) + { + this.handleSearchChanged(nextProps.query); + } }, - componentDidMount: function() { + handleSearchChanged: function(query) { + this.setState({ + searching: true, + query: query, + }); + + lighthouse.search(query, this.searchCallback); + }, + + componentWillMount: function() { document.title = "Discover"; if (this.props.query) { // Rendering with a query already typed @@ -293,7 +300,7 @@ var DiscoverPage = React.createClass({ return { results: [], query: this.props.query, - searching: this.props.query && this.props.query.length > 0 + searching: ('query' in this.props) && (this.props.query.length > 0) }; }, From 70953710a82664ae87a98e1f201f91359ff6ff4d Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Mon, 2 Jan 2017 14:19:37 -0500 Subject: [PATCH 08/13] Help: show Web UI version --- js/page/help.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/js/page/help.js b/js/page/help.js index 75eca13ee..9a492113f 100644 --- a/js/page/help.js +++ b/js/page/help.js @@ -27,7 +27,7 @@ var HelpPage = React.createClass({ document.title = "Help"; }, render: function() { - let ver, osName, platform, newVerLink; + let ver, osName, platform, newVerLink, uiVersion; if (this.state.versionInfo) { ver = this.state.versionInfo; @@ -43,6 +43,12 @@ var HelpPage = React.createClass({ platform = `Windows (${ver.platform})`; newVerLink = 'https://lbry.io/get/lbry.msi'; } + + if (ver.ui_version == 'user-specified') { + uiVersion = '(User specified)'; + } else { + uiVersion = ver.ui_version || '(Unknown)'; + } } else { ver = null; } @@ -86,6 +92,10 @@ var HelpPage = React.createClass({ lbryum (wallet) {ver.lbryum_version} + + lbry-web-ui (interface) + {uiVersion} + Platform {platform} From 0ccc8ca809d4cff3903b873eb3e22aff8055c3d0 Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Mon, 2 Jan 2017 15:42:53 -0500 Subject: [PATCH 09/13] Report: fix imports --- js/page/report.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/page/report.js b/js/page/report.js index 72eedf1a1..6cac655a7 100644 --- a/js/page/report.js +++ b/js/page/report.js @@ -1,4 +1,6 @@ import React from 'react'; +import {Link} from '../component/link.js'; +import Modal from '../component/modal.js'; import lbry from '../lbry.js'; var ReportPage = React.createClass({ From ff61fbbf7accf7800908636412ca5b193d81523a Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Mon, 2 Jan 2017 15:43:34 -0500 Subject: [PATCH 10/13] Update lbry.reportBug() to use new report_bug daemon method --- js/lbry.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/js/lbry.js b/js/lbry.js index e7a7dbd7a..5dbf338ae 100644 --- a/js/lbry.js +++ b/js/lbry.js @@ -386,10 +386,7 @@ lbry.getSessionInfo = function(callback) { } lbry.reportBug = function(message, callback) { - lbry.call('upload_log', { - name_prefix: 'report', - exclude_previous: false, - force: true, + lbry.call('report_bug', { message: message }, callback); } From a2f7f150db3ff9859a6fe3f599357a6a89ecc469 Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Tue, 3 Jan 2017 18:09:59 -0500 Subject: [PATCH 11/13] Import MediaElement with + diff --git a/js/page/watch.js b/js/page/watch.js index 2bc3580e7..c0bc2b67c 100644 --- a/js/page/watch.js +++ b/js/page/watch.js @@ -1,8 +1,6 @@ import React from 'react'; import lbry from '../lbry.js'; import LoadScreen from '../component/load_screen.js' -import MediaElementPlayer from 'mediaelement'; - var WatchPage = React.createClass({ propTypes: { From 304b53e99450daf6d96b26e8483f3e078932dd2c Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Tue, 3 Jan 2017 19:09:46 -0500 Subject: [PATCH 12/13] Simplify sorting logic in My Files --- js/page/my_files.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/js/page/my_files.js b/js/page/my_files.js index 58f662c55..ed33e9fc0 100644 --- a/js/page/my_files.js +++ b/js/page/my_files.js @@ -175,7 +175,6 @@ var MyFilesPage = React.createClass({ }, title: function(filesInfo) { return filesInfo.sort(function(a, b) { - console.log('in title sort. a is', a, '; b is', b) return ((a.metadata ? a.metadata.title.toLowerCase() : a.name) > (b.metadata ? b.metadata.title.toLowerCase() : b.name)); }); @@ -236,15 +235,9 @@ var MyFilesPage = React.createClass({ clearTimeout(this._fileTimeout); } }, - setFilesInfo: function(filesInfo) { - this.setState({ - filesInfo: this._sortFunctions[this.state.sortBy](filesInfo), - }); - }, handleSortChanged: function(event) { this.setState({ sortBy: event.target.value, - filesInfo: this._sortFunctions[event.target.value](this.state.filesInfo), }); }, updateFilesInfo: function() { @@ -263,7 +256,9 @@ var MyFilesPage = React.createClass({ newFilesInfo.push(fileInfo); } if (claimInfoProcessedCount >= claimsInfo.length) { - this.setFilesInfo(newFilesInfo); + this.setState({ + filesInfo: newFilesInfo, + }); this._fileTimeout = setTimeout(() => { this.updateFilesInfo() }, 1000); } @@ -274,9 +269,11 @@ var MyFilesPage = React.createClass({ // We're in the Downloaded tab, so populate this.state.filesInfo with files the user has in // lbrynet, with published files filtered out. lbry.getFilesInfo((filesInfo) => { - this.setFilesInfo(filesInfo.filter(({sd_hash}) => { - return this.state.publishedFilesSdHashes.indexOf(sd_hash) == -1; - })); + this.setState({ + filesInfo: filesInfo.filter(({sd_hash}) => { + return this.state.publishedFilesSdHashes.indexOf(sd_hash) == -1; + }), + }); let newFilesAvailable; if (!(this._fileInfoCheckNum % this._fileInfoCheckRate)) { @@ -320,7 +317,8 @@ var MyFilesPage = React.createClass({ var content = [], seenUris = {}; - for (let fileInfo of this.state.filesInfo) { + const filesInfoSorted = this._sortFunctions[this.state.sortBy](this.state.filesInfo); + for (let fileInfo of filesInfoSorted) { let {completed, written_bytes, total_bytes, lbry_uri, file_name, download_path, stopped, metadata, sd_hash} = fileInfo; From 863758ba541fd7bc7c1767071587dfc0f054c4d5 Mon Sep 17 00:00:00 2001 From: Alex Liebowitz Date: Tue, 3 Jan 2017 19:41:32 -0500 Subject: [PATCH 13/13] My Files: Preserve order of claims returned by daemon --- js/page/my_files.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/js/page/my_files.js b/js/page/my_files.js index ed33e9fc0..fb55a7f23 100644 --- a/js/page/my_files.js +++ b/js/page/my_files.js @@ -246,18 +246,28 @@ var MyFilesPage = React.createClass({ if (this.props.show == 'published') { // We're in the Published tab, so populate this.state.filesInfo with data from the user's claims lbry.getMyClaims((claimsInfo) => { - let newFilesInfo = []; + /** + * Build newFilesInfo as a sparse array and drop elements in at the same position they + * occur in claimsInfo, so the order is preserved even if the API calls inside this loop + * return out of order. + */ + + let newFilesInfo = Array(claimsInfo.length); let claimInfoProcessedCount = 0; - for (let claimInfo of claimsInfo) { + for (let [i, claimInfo] of claimsInfo.entries()) { let metadata = JSON.parse(claimInfo.value); lbry.getFileInfoBySdHash(metadata.sources.lbry_sd_hash, (fileInfo) => { claimInfoProcessedCount++; if (fileInfo !== false) { - newFilesInfo.push(fileInfo); + newFilesInfo[i] = fileInfo; } if (claimInfoProcessedCount >= claimsInfo.length) { + /** + * newFilesInfo may have gaps from claims that don't have associated files in + * lbrynet, so filter out any missing elements + */ this.setState({ - filesInfo: newFilesInfo, + filesInfo: newFilesInfo.filter(function() { return true }), }); this._fileTimeout = setTimeout(() => { this.updateFilesInfo() }, 1000);