feature: display total size by tag or tracker of torrents on sidebar (#369)

Bug: #244
This commit is contained in:
Saber
2021-07-15 00:28:15 +08:00
committed by GitHub
parent aa75f44c70
commit ad764648dd
7 changed files with 63 additions and 4 deletions
@@ -3,6 +3,7 @@ import {FC, ReactNode} from 'react';
import {useLingui} from '@lingui/react';
import Badge from '../general/Badge';
import Size from '../general/Size';
interface SidebarFilterProps {
name: string;
@@ -10,18 +11,26 @@ interface SidebarFilterProps {
isActive: boolean;
slug: string;
count: number;
size?: number;
handleClick: (slug: string) => void;
}
const SidebarFilter: FC<SidebarFilterProps> = (props: SidebarFilterProps) => {
const {isActive, count, slug, icon, handleClick} = props;
const SidebarFilter: FC<SidebarFilterProps> = ({
name: _name,
icon,
isActive,
slug,
count,
size,
handleClick,
}: SidebarFilterProps) => {
const {i18n} = useLingui();
const classNames = classnames('sidebar-filter__item', {
'is-active': isActive,
});
let {name} = props;
let name = _name;
if (name === '') {
name = i18n._('filter.all');
} else if (name === 'untagged') {
@@ -51,8 +60,9 @@ const SidebarFilter: FC<SidebarFilterProps> = (props: SidebarFilterProps) => {
onClick={() => handleClick(slug)}
role="menuitem">
{icon}
{name}
<span className="name">{name}</span>
<Badge>{count}</Badge>
{size && <Size value={size} className="size" />}
</button>
</li>
);
@@ -60,6 +70,7 @@ const SidebarFilter: FC<SidebarFilterProps> = (props: SidebarFilterProps) => {
SidebarFilter.defaultProps = {
icon: undefined,
size: undefined,
};
export default SidebarFilter;
@@ -35,6 +35,7 @@ const TagFilters: FC = observer(() => {
isActive={filter === TorrentFilterStore.filters.tagFilter}
name={filter}
slug={filter}
size={TorrentFilterStore.taxonomy.tagSizes[filter]}
/>
));
@@ -34,6 +34,7 @@ const TrackerFilters: FC = observer(() => {
isActive={filter === TorrentFilterStore.filters.trackerFilter}
name={filter}
slug={filter}
size={TorrentFilterStore.taxonomy.trackerSizes[filter]}
/>
));
@@ -20,7 +20,9 @@ class TorrentFilterStore {
taxonomy: Taxonomy = {
statusCounts: {},
tagCounts: {},
tagSizes: {},
trackerCounts: {},
trackerSizes: {},
};
@computed get isFilterActive() {
@@ -15,6 +15,9 @@
padding: 3px 20px;
text-align: start;
transition: color 0.25s;
display: flex;
align-items: center;
width: 100%;
&:focus-visible,
&:hover {
@@ -53,6 +56,13 @@
}
}
.name {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
max-width: 100px;
}
.icon {
display: inline-block;
@include themes.theme('fill', 'sidebar-filter--foreground');
@@ -62,6 +72,10 @@
vertical-align: middle;
width: auto;
}
.size {
margin-left: auto;
}
}
.badge {
+28
View File
@@ -15,7 +15,9 @@ class TaxonomyService extends BaseService<TaxonomyServiceEvents> {
taxonomy: Taxonomy = {
statusCounts: {'': 0},
tagCounts: {'': 0, untagged: 0},
tagSizes: {},
trackerCounts: {'': 0},
trackerSizes: {},
};
lastTaxonomy: Taxonomy = this.taxonomy;
@@ -61,7 +63,9 @@ class TaxonomyService extends BaseService<TaxonomyServiceEvents> {
this.lastTaxonomy = {
statusCounts: {...this.taxonomy.statusCounts},
tagCounts: {...this.taxonomy.tagCounts},
tagSizes: {...this.taxonomy.tagSizes},
trackerCounts: {...this.taxonomy.trackerCounts},
trackerSizes: {...this.taxonomy.trackerSizes},
};
torrentStatusMap.forEach((status) => {
@@ -70,7 +74,9 @@ class TaxonomyService extends BaseService<TaxonomyServiceEvents> {
this.taxonomy.statusCounts[''] = 0;
this.taxonomy.tagCounts = {'': 0, untagged: 0};
this.taxonomy.tagSizes = {};
this.taxonomy.trackerCounts = {'': 0};
this.taxonomy.trackerSizes = {};
};
handleProcessTorrentListEnd = ({torrents}: {torrents: TorrentList}) => {
@@ -93,7 +99,9 @@ class TaxonomyService extends BaseService<TaxonomyServiceEvents> {
handleProcessTorrent = (torrentProperties: TorrentProperties) => {
this.incrementStatusCounts(torrentProperties.status);
this.incrementTagCounts(torrentProperties.tags);
this.incrementTagSizes(torrentProperties.tags, torrentProperties.sizeBytes);
this.incrementTrackerCounts(torrentProperties.trackerURIs);
this.incrementTrackerSizes(torrentProperties.trackerURIs, torrentProperties.sizeBytes);
};
incrementStatusCounts(statuses: Array<TorrentStatus>) {
@@ -116,6 +124,16 @@ class TaxonomyService extends BaseService<TaxonomyServiceEvents> {
});
}
incrementTagSizes(tags: TorrentProperties['tags'], sizeBytes: TorrentProperties['sizeBytes']) {
tags.forEach((tag) => {
if (this.taxonomy.tagSizes[tag] != null) {
this.taxonomy.tagSizes[tag] += sizeBytes;
} else {
this.taxonomy.tagSizes[tag] = sizeBytes;
}
});
}
incrementTrackerCounts(trackers: TorrentProperties['trackerURIs']) {
trackers.forEach((tracker) => {
if (this.taxonomy.trackerCounts[tracker] != null) {
@@ -125,6 +143,16 @@ class TaxonomyService extends BaseService<TaxonomyServiceEvents> {
}
});
}
incrementTrackerSizes(trackers: TorrentProperties['trackerURIs'], sizeBytes: TorrentProperties['sizeBytes']) {
trackers.forEach((tracker) => {
if (this.taxonomy.trackerSizes[tracker] != null) {
this.taxonomy.trackerSizes[tracker] += sizeBytes;
} else {
this.taxonomy.trackerSizes[tracker] = sizeBytes;
}
});
}
}
export default TaxonomyService;
+2
View File
@@ -1,5 +1,7 @@
export interface Taxonomy {
statusCounts: Record<string, number>;
tagCounts: Record<string, number>;
tagSizes: Record<string, number>;
trackerCounts: Record<string, number>;
trackerSizes: Record<string, number>;
}