client: sortTorrents: rewrite and use fast-sort

This commit is contained in:
Jesse Chan
2020-09-29 19:08:44 +08:00
parent 7ad2245249
commit 57001cea61
4 changed files with 62 additions and 76 deletions
+2 -2
View File
@@ -220,7 +220,7 @@ class TorrentStoreClass extends BaseStore {
switch (diff.action) {
case 'TORRENT_LIST_ACTION_TORRENT_ADDED':
this.torrents[torrentHash] = diff.data as TorrentProperties;
this.torrents[torrentHash] = diff.data;
break;
case 'TORRENT_LIST_ACTION_TORRENT_DELETED':
if (this.selectedTorrents.includes(torrentHash)) {
@@ -266,7 +266,7 @@ class TorrentStoreClass extends BaseStore {
sortTorrents() {
// Convert torrents hash to array and sort it.
this.sortedTorrents = sortTorrents(this.torrents, this.getTorrentsSort());
this.sortedTorrents = sortTorrents(Object.values(this.torrents), this.getTorrentsSort());
}
startPollingTorrentDetails() {
+53 -74
View File
@@ -1,83 +1,62 @@
import type {Duration, TorrentProperties, Torrents} from '@shared/types/Torrent';
import sort from 'fast-sort';
import type {TorrentProperties} from '@shared/types/Torrent';
import type {FloodSettings} from '../stores/SettingsStore';
const stringProps = ['basePath', 'comment', 'hash', 'message', 'name'];
type SortRule = {
[direction in FloodSettings['sortTorrents']['direction']]:
| keyof TorrentProperties
| ((p: TorrentProperties) => unknown);
};
// TODO: Split up this garbage.
function sortTorrents(torrentsHash: Torrents, sortBy: FloodSettings['sortTorrents']) {
const torrents = Object.keys(torrentsHash).map((hash) => ({...torrentsHash[hash]}));
function sortTorrents(torrents: Array<TorrentProperties>, sortBy: Readonly<FloodSettings['sortTorrents']>) {
const {property} = sortBy;
const sortRules: Array<SortRule> = [];
if (torrents.length) {
const {direction, property} = sortBy;
torrents.sort((a, b) => {
let valA = a[property as keyof TorrentProperties];
let valB = b[property as keyof TorrentProperties];
if (property === 'peers' || property === 'seeds') {
valA = a[`${property}Connected` as keyof TorrentProperties];
valB = b[`${property}Connected` as keyof TorrentProperties];
if (valA === valB) {
valA = a[`${property}Total` as keyof TorrentProperties];
valB = b[`${property}Total` as keyof TorrentProperties];
}
} else if (property === 'eta') {
// Keep Infinity and null values at bottom of array.
if ((valA === 'Infinity' && valB !== 'Infinity') || (valA == null && valB != null)) {
return 1;
}
if ((valA !== 'Infinity' && valB === 'Infinity') || (valA != null && valB == null)) {
return -1;
}
if (valA == null && valB == null) {
return 0;
}
// If it's not infinity, compare the cumulative seconds as regular numbers.
if (valA !== 'Infinity') {
valA = Number((valA as Duration).cumSeconds);
}
if (valB !== 'Infinity') {
valB = Number((valB as Duration).cumSeconds);
}
} else if (property === 'tags') {
// TODO: Find a better way to sort tags.
valA = (valA as TorrentProperties['tags']).join(',').toLowerCase();
valB = (valB as TorrentProperties['tags']).join(',').toLowerCase();
} else if (stringProps.includes(property)) {
valA = (valA as string).toLowerCase();
valB = (valB as string).toLowerCase();
} else {
valA = Number(valA);
valB = Number(valB);
}
// TODO: Use locale compare for sorting strings.
if (direction === 'asc') {
if (valA > valB) {
return 1;
}
if (valA < valB) {
return -1;
}
} else {
if (valA > valB) {
return -1;
}
if (valA < valB) {
return 1;
}
}
return 0;
});
return torrents;
switch (property) {
case 'peers':
case 'seeds':
sortRules.push(
{[sortBy.direction]: `${property}Connected`} as SortRule,
{[sortBy.direction]: `${property}Total`} as SortRule,
);
break;
case 'eta':
sortRules.push({
[sortBy.direction]: (p: TorrentProperties) => {
if (p.eta === 'Infinity') {
return -1;
}
return p.eta.cumSeconds;
},
} as SortRule);
break;
case 'tags':
sortRules.push({
[sortBy.direction]: (p: TorrentProperties) => {
return p[property].join(',').toLowerCase();
},
} as SortRule);
break;
case 'basePath':
case 'comment':
case 'hash':
case 'message':
case 'name':
// Those fields are strings. We want case-insensitive sorting.
sortRules.push({
[sortBy.direction]: (p: TorrentProperties) => {
return p[property].toLowerCase();
},
} as SortRule);
break;
default:
sortRules.push({[sortBy.direction]: property} as SortRule);
break;
}
return torrents;
return sort(torrents).by(sortRules);
}
export default sortTorrents;
+6
View File
@@ -7695,6 +7695,12 @@
"integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==",
"dev": true
},
"fast-sort": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/fast-sort/-/fast-sort-2.2.0.tgz",
"integrity": "sha512-W7zqnn2zsYoQA87FKmYtgOsbJohOrh7XrtZrCVHN5XZKqTBTv5UG+rSS3+iWbg/nepRQUOu+wnas8BwtK8kiCg==",
"dev": true
},
"fastparse": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+1
View File
@@ -108,6 +108,7 @@
"eslint-plugin-react": "^7.21.2",
"eslint-plugin-react-hooks": "^4.1.2",
"express": "^4.17.1",
"fast-sort": "^2.2.0",
"feedsub": "^0.7.1",
"file-loader": "^6.1.0",
"flux": "^3.1.3",