From 7a6dd93886dd66a2a6b127b8853161cf8fd7badb Mon Sep 17 00:00:00 2001
From: 6ea86b96 <6ea86b96@gmail.com>
Date: Sun, 30 Apr 2017 23:01:43 +0700
Subject: [PATCH] Downloaded file list kind of working. Not sure about sort.
---
ui/js/actions/app.js | 17 +-
ui/js/actions/content.js | 12 ++
ui/js/actions/file_info.js | 24 +++
ui/js/component/fileList/index.js | 8 +-
ui/js/component/fileList/view.jsx | 233 +++++++++++++++++--------
ui/js/component/header/index.js | 2 +
ui/js/component/header/view.jsx | 2 +-
ui/js/page/fileListDownloaded/index.js | 10 +-
ui/js/page/fileListDownloaded/view.jsx | 53 +-----
ui/js/reducers/file_info.js | 21 +++
ui/js/selectors/app.js | 28 +++
ui/js/selectors/file_info.js | 16 ++
12 files changed, 291 insertions(+), 135 deletions(-)
diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js
index 073ae9099..d2c7679f3 100644
--- a/ui/js/actions/app.js
+++ b/ui/js/actions/app.js
@@ -5,6 +5,7 @@ import {
selectUpgradeDownloadDir,
selectUpgradeDownloadItem,
selectUpgradeFilename,
+ selectPageTitle,
} from 'selectors/app'
const {remote, ipcRenderer, shell} = require('electron');
@@ -14,11 +15,17 @@ const {download} = remote.require('electron-dl');
const fs = remote.require('fs');
export function doNavigate(path) {
- return {
- type: types.NAVIGATE,
- data: {
- path: path
- }
+ return function(dispatch, getState) {
+ dispatch({
+ type: types.NAVIGATE,
+ data: {
+ path,
+ }
+ })
+
+ const state = getState()
+ const pageTitle = selectPageTitle(state)
+ window.document.title = pageTitle
}
}
diff --git a/ui/js/actions/content.js b/ui/js/actions/content.js
index 9e9f90e3d..0e5c28086 100644
--- a/ui/js/actions/content.js
+++ b/ui/js/actions/content.js
@@ -20,6 +20,9 @@ import {
import {
selectCurrentResolvedUriClaimOutpoint,
} from 'selectors/content'
+import {
+ selectClaimsByUri,
+} from 'selectors/claims'
import {
doOpenModal,
} from 'actions/app'
@@ -67,6 +70,15 @@ export function doFetchDownloadedContent() {
lbry.file_list().then((fileInfos) => {
const myClaimOutpoints = myClaimInfos.map(({txid, nout}) => txid + ':' + nout);
+ fileInfos.forEach(fileInfo => {
+ const uri = lbryuri.build({
+ channelName: fileInfo.channel_name,
+ contentName: fileInfo.name,
+ })
+ const claim = selectClaimsByUri(state)[uri]
+ if (!claim) dispatch(doResolveUri(uri))
+ })
+
dispatch({
type: types.FETCH_DOWNLOADED_CONTENT_COMPLETED,
data: {
diff --git a/ui/js/actions/file_info.js b/ui/js/actions/file_info.js
index 77763352b..b7611fb3d 100644
--- a/ui/js/actions/file_info.js
+++ b/ui/js/actions/file_info.js
@@ -76,3 +76,27 @@ export function doDeleteFile(uri, fileInfo, deleteFromComputer) {
lbry.removeFile(fileInfo.outpoint, deleteFromComputer, successCallback)
}
}
+
+export function doFetchDownloadedContent() {
+ return function(dispatch, getState) {
+ const state = getState()
+
+ dispatch({
+ type: types.FETCH_DOWNLOADED_CONTENT_STARTED,
+ })
+
+ lbry.claim_list_mine().then((myClaimInfos) => {
+ lbry.file_list().then((fileInfos) => {
+ const myClaimOutpoints = myClaimInfos.map(({txid, nout}) => txid + ':' + nout);
+
+ dispatch({
+ type: types.FETCH_DOWNLOADED_CONTENT_COMPLETED,
+ data: {
+ fileInfos: fileInfos.filter(({outpoint}) => !myClaimOutpoints.includes(outpoint)),
+ }
+ })
+ });
+ });
+ }
+}
+
diff --git a/ui/js/component/fileList/index.js b/ui/js/component/fileList/index.js
index 0a6c65c70..dd0209b40 100644
--- a/ui/js/component/fileList/index.js
+++ b/ui/js/component/fileList/index.js
@@ -4,4 +4,10 @@ import {
} from 'react-redux'
import FileList from './view'
-export default connect()(FileList)
+const select = (state) => ({
+})
+
+const perform = (dispatch) => ({
+})
+
+export default connect(select, perform)(FileList)
diff --git a/ui/js/component/fileList/view.jsx b/ui/js/component/fileList/view.jsx
index a119f8792..2a946746c 100644
--- a/ui/js/component/fileList/view.jsx
+++ b/ui/js/component/fileList/view.jsx
@@ -3,90 +3,81 @@ import lbry from 'lbry.js';
import lbryuri from 'lbryuri.js';
import Link from 'component/link';
import {FormField} from 'component/form.js';
-import FileTileStream from 'component/fileTile';
+import FileTileStream from 'component/fileTileStream';
import rewards from 'rewards.js';
import lbryio from 'lbryio.js';
import {BusyMessage, Thumbnail} from 'component/common.js';
-const FileList = React.createClass({
- _sortFunctions: {
- date: function(fileInfos) {
- return fileInfos.slice().reverse();
- },
- title: function(fileInfos) {
- return fileInfos.slice().sort(function(fileInfo1, fileInfo2) {
- const title1 = fileInfo1.metadata ? fileInfo1.metadata.title.toLowerCase() : fileInfo1.name;
- const title2 = fileInfo2.metadata ? fileInfo2.metadata.title.toLowerCase() : fileInfo2.name;
- if (title1 < title2) {
- return -1;
- } else if (title1 > title2) {
- return 1;
- } else {
- return 0;
- }
- });
- },
- filename: function(fileInfos) {
- return fileInfos.slice().sort(function({file_name: fileName1}, {file_name: fileName2}) {
- const fileName1Lower = fileName1.toLowerCase();
- const fileName2Lower = fileName2.toLowerCase();
- if (fileName1Lower < fileName2Lower) {
- return -1;
- } else if (fileName2Lower > fileName1Lower) {
- return 1;
- } else {
- return 0;
- }
- });
- },
- },
- propTypes: {
- fileInfos: React.PropTypes.array.isRequired,
- hidePrices: React.PropTypes.bool,
- },
- getDefaultProps: function() {
- return {
- hidePrices: false,
- };
- },
- getInitialState: function() {
- return {
+class FileList extends React.Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
sortBy: 'date',
- };
- },
- handleSortChanged: function(event) {
- this.setState({
- sortBy: event.target.value,
- });
- },
- render: function() {
- var content = [],
- seenUris = {};
-
- const fileInfosSorted = this._sortFunctions[this.state.sortBy](this.props.fileInfos);
- for (let {outpoint, name, channel_name, metadata, mime_type, claim_id, has_signature, signature_is_valid} of fileInfosSorted) {
- if (seenUris[name] || !claim_id) {
- continue;
- }
-
- let streamMetadata;
- if (metadata) {
- streamMetadata = metadata.stream.metadata;
- } else {
- streamMetadata = null;
- }
-
-
- const uri = lbryuri.build({contentName: name, channelName: channel_name});
- seenUris[name] = true;
- content.push()
}
+ this._sortFunctions = {
+ date: function(fileInfos) {
+ return fileInfos.slice().reverse();
+ },
+ title: function(fileInfos) {
+ return fileInfos.slice().sort(function(fileInfo1, fileInfo2) {
+ const title1 = fileInfo1.metadata ? fileInfo1.metadata.stream.metadata.title.toLowerCase() : fileInfo1.name;
+ const title2 = fileInfo2.metadata ? fileInfo2.metadata.stream.metadata.title.toLowerCase() : fileInfo2.name;
+ if (title1 < title2) {
+ return -1;
+ } else if (title1 > title2) {
+ return 1;
+ } else {
+ return 0;
+ }
+ })
+ },
+ filename: function(fileInfos) {
+ return fileInfos.slice().sort(function({file_name: fileName1}, {file_name: fileName2}) {
+ const fileName1Lower = fileName1.toLowerCase();
+ const fileName2Lower = fileName2.toLowerCase();
+ if (fileName1Lower < fileName2Lower) {
+ return -1;
+ } else if (fileName2Lower > fileName1Lower) {
+ return 1;
+ } else {
+ return 0;
+ }
+ })
+ },
+ }
+ }
+
+ handleSortChanged(event) {
+ this.setState({
+ sortBy: event.target.value,
+ })
+ }
+
+ render() {
+ const {
+ handleSortChanged,
+ fileInfos,
+ hidePrices,
+ } = this.props
+ const {
+ sortBy,
+ } = this.state
+ const content = []
+
+ this._sortFunctions[sortBy](fileInfos).forEach(fileInfo => {
+ const uri = lbryuri.build({
+ contentName: fileInfo.name,
+ channelName: fileInfo.channel_name,
+ })
+ content.push()
+ })
return (
Sort by { ' ' }
-
+
@@ -94,8 +85,100 @@ const FileList = React.createClass({
{content}
- );
+ )
}
-});
+}
+
+// const FileList = React.createClass({
+// _sortFunctions: {
+// date: function(fileInfos) {
+// return fileInfos.slice().reverse();
+// },
+// title: function(fileInfos) {
+// return fileInfos.slice().sort(function(fileInfo1, fileInfo2) {
+// const title1 = fileInfo1.metadata ? fileInfo1.metadata.title.toLowerCase() : fileInfo1.name;
+// const title2 = fileInfo2.metadata ? fileInfo2.metadata.title.toLowerCase() : fileInfo2.name;
+// if (title1 < title2) {
+// return -1;
+// } else if (title1 > title2) {
+// return 1;
+// } else {
+// return 0;
+// }
+// });
+// },
+// filename: function(fileInfos) {
+// return fileInfos.slice().sort(function({file_name: fileName1}, {file_name: fileName2}) {
+// const fileName1Lower = fileName1.toLowerCase();
+// const fileName2Lower = fileName2.toLowerCase();
+// if (fileName1Lower < fileName2Lower) {
+// return -1;
+// } else if (fileName2Lower > fileName1Lower) {
+// return 1;
+// } else {
+// return 0;
+// }
+// });
+// },
+// },
+// propTypes: {
+// fileInfos: React.PropTypes.array.isRequired,
+// hidePrices: React.PropTypes.bool,
+// },
+// getDefaultProps: function() {
+// return {
+// hidePrices: false,
+// };
+// },
+// getInitialState: function() {
+// return {
+// sortBy: 'date',
+// };
+// },
+// handleSortChanged: function(event) {
+// this.setState({
+// sortBy: event.target.value,
+// });
+// },
+// render: function() {
+// var content = [],
+// seenUris = {};
+
+// console.debug(this.props)
+
+// const fileInfosSorted = this._sortFunctions[this.state.sortBy](this.props.fileInfos);
+// for (let {outpoint, name, channel_name, metadata, mime_type, claim_id, has_signature, signature_is_valid} of fileInfosSorted) {
+// if (seenUris[name] || !claim_id) {
+// continue;
+// }
+
+// let streamMetadata;
+// if (metadata) {
+// streamMetadata = metadata.stream.metadata;
+// } else {
+// streamMetadata = null;
+// }
+
+
+// const uri = lbryuri.build({contentName: name, channelName: channel_name});
+// seenUris[name] = true;
+// content.push()
+// }
+
+// return (
+//
+//
+// Sort by { ' ' }
+//
+//
+//
+//
+//
+//
+// {content}
+//
+// );
+// }
+// });
export default FileList
diff --git a/ui/js/component/header/index.js b/ui/js/component/header/index.js
index 02ca2f2f8..ce5cefdd8 100644
--- a/ui/js/component/header/index.js
+++ b/ui/js/component/header/index.js
@@ -5,6 +5,7 @@ import {
import {
selectCurrentPage,
selectHeaderLinks,
+ selectPageTitle,
} from 'selectors/app'
import {
doNavigate,
@@ -19,6 +20,7 @@ import Header from './view'
const select = (state) => ({
currentPage: selectCurrentPage(state),
subLinks: selectHeaderLinks(state),
+ pageTitle: selectPageTitle(state),
})
const perform = (dispatch) => ({
diff --git a/ui/js/component/header/view.jsx b/ui/js/component/header/view.jsx
index e54bf3751..92a45cad9 100644
--- a/ui/js/component/header/view.jsx
+++ b/ui/js/component/header/view.jsx
@@ -104,7 +104,7 @@ class WunderBar extends React.PureComponent {
this.props.onSearch(searchTerm);
}, 800); // 800ms delay, tweak for faster/slower
}
-
+
componentWillReceiveProps(nextProps) {
if (nextProps.viewingPage !== this.props.viewingPage || nextProps.address != this.props.address) {
this.setState({ address: nextProps.address, icon: nextProps.icon });
diff --git a/ui/js/page/fileListDownloaded/index.js b/ui/js/page/fileListDownloaded/index.js
index ed27152c5..6d92a1867 100644
--- a/ui/js/page/fileListDownloaded/index.js
+++ b/ui/js/page/fileListDownloaded/index.js
@@ -3,17 +3,23 @@ import {
connect
} from 'react-redux'
import {
- selectDownloadedContentFileInfos,
selectFetchingDownloadedContent,
} from 'selectors/content'
+import {
+ selectDownloadedFileInfo,
+} from 'selectors/file_info'
+import {
+ doNavigate,
+} from 'actions/app'
import FileListDownloaded from './view'
const select = (state) => ({
- downloadedContent: selectDownloadedContentFileInfos(state),
+ downloadedContent: selectDownloadedFileInfo(state),
fetching: selectFetchingDownloadedContent(state),
})
const perform = (dispatch) => ({
+ navigate: (path) => dispatch(doNavigate(path)),
})
export default connect(select, perform)(FileListDownloaded)
diff --git a/ui/js/page/fileListDownloaded/view.jsx b/ui/js/page/fileListDownloaded/view.jsx
index 715eae94e..cf95e0224 100644
--- a/ui/js/page/fileListDownloaded/view.jsx
+++ b/ui/js/page/fileListDownloaded/view.jsx
@@ -14,6 +14,7 @@ class FileListDownloaded extends React.Component {
const {
downloadedContent,
fetching,
+ navigate,
} = this.props
if (fetching) {
@@ -25,7 +26,7 @@ class FileListDownloaded extends React.Component {
} else if (!downloadedContent.length) {
return (
- You haven't downloaded anything from LBRY yet. Go !
+ You haven't downloaded anything from LBRY yet. Go navigate('discover')} label="search for your first download" />!
);
} else {
@@ -37,55 +38,5 @@ class FileListDownloaded extends React.Component {
}
}
}
-// const FileListDownloaded = React.createClass({
-// _isMounted: false,
-
-// getInitialState: function() {
-// return {
-// fileInfos: null,
-// };
-// },
-// componentDidMount: function() {
-// this._isMounted = true;
-// document.title = "Downloaded Files";
-
-// lbry.claim_list_mine().then((myClaimInfos) => {
-// if (!this._isMounted) { return; }
-
-// lbry.file_list().then((fileInfos) => {
-// if (!this._isMounted) { return; }
-
-// const myClaimOutpoints = myClaimInfos.map(({txid, nout}) => txid + ':' + nout);
-// this.setState({
-// fileInfos: fileInfos.filter(({outpoint}) => !myClaimOutpoints.includes(outpoint)),
-// });
-// });
-// });
-// },
-// componentWillUnmount: function() {
-// this._isMounted = false;
-// },
-// render: function() {
-// if (this.state.fileInfos === null) {
-// return (
-//
-//
-//
-// );
-// } else if (!this.state.fileInfos.length) {
-// return (
-//
-// You haven't downloaded anything from LBRY yet. Go !
-//
-// );
-// } else {
-// return (
-//
-//
-//
-// );
-// }
-// }
-// });
export default FileListDownloaded
diff --git a/ui/js/reducers/file_info.js b/ui/js/reducers/file_info.js
index 2c98cf048..0023df8f1 100644
--- a/ui/js/reducers/file_info.js
+++ b/ui/js/reducers/file_info.js
@@ -1,4 +1,5 @@
import * as types from 'constants/action_types'
+import lbryuri from 'lbryuri'
const reducers = {}
const defaultState = {
@@ -157,6 +158,26 @@ reducers[types.LOADING_VIDEO_FAILED] = function(state, action) {
})
}
+reducers[types.FETCH_DOWNLOADED_CONTENT_COMPLETED] = function(state, action) {
+ const {
+ fileInfos,
+ } = action.data
+ const newByUri = Object.assign({}, state.byUri)
+
+ fileInfos.forEach(fileInfo => {
+ const uri = lbryuri.build({
+ channelName: fileInfo.channel_name,
+ contentName: fileInfo.name,
+ })
+
+ newByUri[uri] = fileInfo
+ })
+
+ return Object.assign({}, state, {
+ byUri: newByUri
+ })
+}
+
export default function reducer(state = defaultState, action) {
const handler = reducers[action.type];
if (handler) return handler(state, action);
diff --git a/ui/js/selectors/app.js b/ui/js/selectors/app.js
index 7105bc16b..a269e98f2 100644
--- a/ui/js/selectors/app.js
+++ b/ui/js/selectors/app.js
@@ -28,6 +28,34 @@ export const selectCurrentUri = createSelector(
}
)
+export const selectPageTitle = createSelector(
+ selectCurrentPage,
+ selectCurrentUri,
+ (page, uri) => {
+ switch(page)
+ {
+ case 'discover':
+ return 'Discover'
+ case 'wallet':
+ case 'send':
+ case 'receive':
+ case 'claim':
+ case 'referral':
+ return 'Wallet'
+ case 'downloaded':
+ return 'My Files'
+ case 'published':
+ return 'My Files'
+ case 'publish':
+ return 'Publish'
+ case 'help':
+ return 'Help'
+ default:
+ return 'LBRY';
+ }
+ }
+)
+
export const selectPlatform = createSelector(
_selectState,
(state) => state.platform
diff --git a/ui/js/selectors/file_info.js b/ui/js/selectors/file_info.js
index 79b28c1d6..0a114ba0f 100644
--- a/ui/js/selectors/file_info.js
+++ b/ui/js/selectors/file_info.js
@@ -133,3 +133,19 @@ export const makeSelectLoadingForUri = () => {
(loading) => !!loading
)
}
+
+export const selectDownloadedFileInfo = createSelector(
+ selectAllFileInfoByUri,
+ (byUri) => {
+ const fileInfoList = []
+ Object.keys(byUri).forEach(key => {
+ const fileInfo = byUri[key]
+
+ if (fileInfo.completed || fileInfo.written_bytes) {
+ fileInfoList.push(fileInfo)
+ }
+ })
+
+ return fileInfoList
+ }
+)