diff --git a/client/source/sass/components/_torrents.scss b/client/source/sass/components/_torrents.scss
index 58de40ae..94241b37 100644
--- a/client/source/sass/components/_torrents.scss
+++ b/client/source/sass/components/_torrents.scss
@@ -1,5 +1,6 @@
$torrent-list--background: #fff;
$torrent-list--border: rgba($background, 0.15);
+$torrent-list--offset: 10px;
$torrent--primary--foreground: #5b6d7c;
$torrent--primary--foreground--error: #e95779;
@@ -14,6 +15,7 @@ $torrent--tertiary--foreground: #8899a8;
$torrent--tertiary--foreground--stopped: rgba(#8899a8, 0.5);
$torrent--tertiary--foreground--selected: rgba(#fff, 0.9);
$torrent--tertiary--foreground--selected--stopped: rgba(#fff, 0.5);
+$torrent--notification--foreground: $torrent--tertiary--foreground--stopped;
$torrent--background--hover: #f6f8fa;
$torrent--background--selected: $blue;
@@ -34,7 +36,7 @@ $more-info--border: $textbox-repeater--button--border;
box-shadow: -1px 0 0 0 $torrent-list--border;
content: '';
height: auto;
- left: 10px;
+ left: $torrent-list--offset;
position: absolute;
right: 0;
top: 0;
@@ -46,6 +48,22 @@ $more-info--border: $textbox-repeater--button--border;
top: 50%;
transform: translate(-50%, -50%);
}
+
+ &__notification {
+ color: $torrent--notification--foreground;
+ text-align: center;
+
+ &__wrapper {
+ justify-content: center;
+ align-items: center;
+ bottom: 0;
+ display: flex;
+ left: $torrent-list--offset;
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+ }
}
.torrent {
diff --git a/client/source/scripts/actions/TorrentActions.js b/client/source/scripts/actions/TorrentActions.js
index 2757d415..cd577201 100644
--- a/client/source/scripts/actions/TorrentActions.js
+++ b/client/source/scripts/actions/TorrentActions.js
@@ -93,7 +93,7 @@ const TorrentActions = {
});
})
.catch((error) => {
- console.log(error);
+ console.trace(error);
AppDispatcher.dispatchServerAction({
type: ActionTypes.CLIENT_FETCH_TORRENTS_ERROR,
data: {
diff --git a/client/source/scripts/components/sidebar/TrackerFilters.js b/client/source/scripts/components/sidebar/TrackerFilters.js
index 3dae3430..c5e57428 100644
--- a/client/source/scripts/components/sidebar/TrackerFilters.js
+++ b/client/source/scripts/components/sidebar/TrackerFilters.js
@@ -114,6 +114,10 @@ export default class TrackerFilters extends React.Component {
render() {
let filters = this.getFilters();
+ if (filters.length === 0) {
+ return null;
+ }
+
return (
-
diff --git a/client/source/scripts/components/torrent-list/TorrentList.js b/client/source/scripts/components/torrent-list/TorrentList.js
index 7749dd47..e1424526 100644
--- a/client/source/scripts/components/torrent-list/TorrentList.js
+++ b/client/source/scripts/components/torrent-list/TorrentList.js
@@ -19,17 +19,18 @@ import UIStore from '../../stores/UIStore';
const METHODS_TO_BIND = [
'bindExternalPriorityChangeHandler',
- 'onReceiveTorrentsError',
- 'onReceiveTorrentsSuccess',
+ 'getListPadding',
+ 'getViewportLimits',
'handleContextMenuItemClick',
'handleDetailsClick',
'handleRightClick',
'handleTorrentClick',
'onContextMenuChange',
+ 'onEmptyTorrentResponse',
+ 'onReceiveTorrentsError',
+ 'onReceiveTorrentsSuccess',
'onTorrentFilterChange',
'onTorrentSelectionChange',
- 'getListPadding',
- 'getViewportLimits',
'setScrollPosition',
'setViewportHeight'
];
@@ -39,6 +40,7 @@ export default class TorrentListContainer extends React.Component {
super();
this.state = {
+ emptyTorrentList: false,
handleTorrentPriorityChange: null,
contextMenu: null,
maxTorrentIndex: 10,
@@ -46,7 +48,7 @@ export default class TorrentListContainer extends React.Component {
scrollPosition: 0,
torrentCount: 0,
torrentHeight: 72,
- torrents: null,
+ torrents: [],
torrentRequestError: false,
torrentRequestSuccess: false,
viewportHeight: 0
@@ -72,6 +74,7 @@ export default class TorrentListContainer extends React.Component {
TorrentStore.listen(EventTypes.UI_TORRENT_SELECTION_CHANGE, this.onTorrentSelectionChange);
TorrentStore.listen(EventTypes.CLIENT_TORRENTS_REQUEST_SUCCESS, this.onReceiveTorrentsSuccess);
TorrentStore.listen(EventTypes.CLIENT_TORRENTS_REQUEST_ERROR, this.onReceiveTorrentsError);
+ TorrentStore.listen(EventTypes.CLIENT_TORRENTS_EMPTY, this.onEmptyTorrentResponse);
TorrentFilterStore.listen(EventTypes.UI_TORRENTS_FILTER_CHANGE, this.onTorrentFilterChange);
UIStore.listen(EventTypes.UI_CONTEXT_MENU_CHANGE, this.onContextMenuChange);
TorrentStore.fetchTorrents();
@@ -84,6 +87,7 @@ export default class TorrentListContainer extends React.Component {
TorrentStore.unlisten(EventTypes.UI_TORRENT_SELECTION_CHANGE, this.onTorrentSelectionChange);
TorrentStore.unlisten(EventTypes.CLIENT_TORRENTS_REQUEST_SUCCESS, this.onReceiveTorrentsSuccess);
TorrentStore.unlisten(EventTypes.CLIENT_TORRENTS_REQUEST_ERROR, this.onReceiveTorrentsError);
+ TorrentStore.unlisten(EventTypes.CLIENT_TORRENTS_EMPTY, this.onEmptyTorrentResponse);
TorrentFilterStore.unlisten(EventTypes.UI_TORRENTS_FILTER_CHANGE, this.onTorrentFilterChange);
UIStore.unlisten(EventTypes.UI_CONTEXT_MENU_CHANGE, this.onContextMenuChange);
}
@@ -194,6 +198,18 @@ export default class TorrentListContainer extends React.Component {
this.setState({contextMenu: UIStore.getActiveContextMenu()});
}
+ onEmptyTorrentResponse() {
+ this.setState({
+ emptyTorrentList: true,
+ torrentRequestError: false,
+ torrentRequestSuccess: true
+ });
+
+ if (!UIStore.hasSatisfiedDependencies()) {
+ UIStore.satisfyDependency('torrent-list');
+ }
+ }
+
onReceiveTorrentsError() {
this.setState({torrentRequestError: true, torrentRequestSuccess: false});
}
@@ -221,6 +237,16 @@ export default class TorrentListContainer extends React.Component {
this.forceUpdate();
}
+ getEmptyTorrentListNotification() {
+ return (
+
+
+ No torrents to display.
+
+
+ );
+ }
+
getListPadding(minTorrentIndex, maxTorrentIndex, torrentCount) {
// Calculate the number of pixels to pad the visible item list.
// If the minimum item index is less than 0, then we're already at the top
@@ -345,6 +371,10 @@ export default class TorrentListContainer extends React.Component {
);
}
+ if (this.state.emptyTorrentList) {
+ content = this.getEmptyTorrentListNotification();
+ }
+
return (
{
+ if (!data || data[0][0].length === 0) {
+ return null;
+ }
+
// TODO: Remove this nasty nested array business.
_torrentCollection.updateTorrents(data[0][0]);
_statusCount = _torrentCollection.statusCount;
diff --git a/server/util/clientUtil.js b/server/util/clientUtil.js
index ae153297..1f92c21e 100644
--- a/server/util/clientUtil.js
+++ b/server/util/clientUtil.js
@@ -220,7 +220,7 @@ var clientUtil = {
},
// TODO clean this up, write comments...
- mapClientProps: (props, data, includeIndex) => {
+ mapClientProps: (props, data) => {
var index = 0;
var mappedObject = [];