Skip to content

Commit

Permalink
perf(Dashboard): Sort forced ETA 0s as infinity (#2110)
Browse files Browse the repository at this point in the history
  • Loading branch information
Larsluph authored Dec 31, 2024
1 parent c761591 commit f262eca
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 38 deletions.
6 changes: 3 additions & 3 deletions src/constants/vuetorrent/Comparators.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import comparators from '@/helpers/comparators'
import Torrent from '@/types/vuetorrent/Torrent'
import { comparators, QBIT_MAX_ETA } from '@/helpers'
import { Torrent } from '@/types/vuetorrent'

const comparatorMap: Record<keyof Torrent, (a: Torrent, b: Torrent, isAsc: boolean) => number> = {
added_on: (a, b, isAsc) => comparators.numeric.compare(a.added_on, b.added_on, isAsc),
Expand All @@ -21,7 +21,7 @@ const comparatorMap: Record<keyof Torrent, (a: Torrent, b: Torrent, isAsc: boole
download_path: (a, b, isAsc) => comparators.textWithNumbers.compare(a.download_path, b.download_path, isAsc),
downloaded: (a, b, isAsc) => comparators.numeric.compare(a.downloaded, b.downloaded, isAsc),
downloaded_session: (a, b, isAsc) => comparators.numeric.compare(a.downloaded_session, b.downloaded_session, isAsc),
eta: (a, b, isAsc) => comparators.numeric.compare(a.eta, b.eta, isAsc),
eta: (a, b, isAsc) => comparators.numeric.compare(a.eta === 0 && a.forced ? QBIT_MAX_ETA : a.eta, b.eta === 0 && b.forced ? QBIT_MAX_ETA : b.eta, isAsc),
f_l_piece_prio: (a, b, isAsc) => comparators.boolean.compare(a.f_l_piece_prio, b.f_l_piece_prio, isAsc),
forced: (a, b, isAsc) => comparators.boolean.compare(a.forced, b.forced, isAsc),
globalSpeed: (a, b, isAsc) => comparators.numeric.compare(a.globalSpeed, b.globalSpeed, isAsc),
Expand Down
2 changes: 1 addition & 1 deletion src/constants/vuetorrent/DashboardDefaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ export const propsMetadata: PropertyMetadata = {
type: DashboardPropertyType.DATA
},
[DashboardProperty.ETA]: {
props: { titleKey: 'torrent.properties.eta', value: t => formatEta(t.eta) },
props: { titleKey: 'torrent.properties.eta', value: t => formatEta(t.eta, t.forced) },
sortKey: 'eta',
type: DashboardPropertyType.TEXT
},
Expand Down
66 changes: 38 additions & 28 deletions src/helpers/datetime.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import timezoneMock from 'timezone-mock'
import { expect, test } from 'vitest'
import { formatDuration, formatEta, formatTimeMs, formatTimeSec } from './datetime'
import { describe, expect, test } from 'vitest'
import { formatDuration, formatEta, formatTimeMs, formatTimeSec, INFINITY_SYMBOL, QBIT_MAX_ETA } from './datetime'

beforeAll(() => {
timezoneMock.register('UTC')
Expand All @@ -10,32 +10,42 @@ afterAll(() => {
timezoneMock.unregister()
})

test('helpers/datetime/formatEta', () => {
// seconds
expect(formatEta(0)).toBe('0s')
expect(formatEta(1)).toBe('1s')
expect(formatEta(59)).toBe('59s')

// minutes
expect(formatEta(60)).toBe('1m')
expect(formatEta(61)).toBe('1m 1s')
expect(formatEta(3599)).toBe('59m 59s')

// hours
expect(formatEta(3600)).toBe('1h')
expect(formatEta(3601)).toBe('1h 1s')
expect(formatEta(3660)).toBe('1h 1m')
expect(formatEta(3661)).toBe('1h 1m')
expect(formatEta(86399)).toBe('23h 59m')

// days
expect(formatEta(86400)).toBe('1d')
expect(formatEta(86401)).toBe('1d 1s')
expect(formatEta(86460)).toBe('1d 1m')
expect(formatEta(86461)).toBe('1d 1m')
expect(formatEta(90000)).toBe('1d 1h')
expect(formatEta(90001)).toBe('1d 1h')
expect(formatEta(90060)).toBe('1d 1h')
describe('helpers/datetime/formatEta', () => {
test('seconds', () => {
expect(formatEta(1)).toBe('1s')
expect(formatEta(59)).toBe('59s')
})

test('minutes', () => {
expect(formatEta(60)).toBe('1m')
expect(formatEta(61)).toBe('1m 1s')
expect(formatEta(3599)).toBe('59m 59s')
})

test('hours', () => {
expect(formatEta(3600)).toBe('1h')
expect(formatEta(3601)).toBe('1h 1s')
expect(formatEta(3660)).toBe('1h 1m')
expect(formatEta(3661)).toBe('1h 1m')
expect(formatEta(86399)).toBe('23h 59m')
})

test('days', () => {
expect(formatEta(86400)).toBe('1d')
expect(formatEta(86401)).toBe('1d 1s')
expect(formatEta(86460)).toBe('1d 1m')
expect(formatEta(86461)).toBe('1d 1m')
expect(formatEta(90000)).toBe('1d 1h')
expect(formatEta(90001)).toBe('1d 1h')
expect(formatEta(90060)).toBe('1d 1h')
})

test('infinity', () => {
expect(formatEta(0)).toBe('0s')
expect(formatEta(0, false)).toBe('0s')
expect(formatEta(0, true)).toBe(INFINITY_SYMBOL)
expect(formatEta(QBIT_MAX_ETA)).toBe(INFINITY_SYMBOL)
})
})

test('helpers/datetime/formatTimeMs', () => {
Expand Down
10 changes: 6 additions & 4 deletions src/helpers/datetime.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import dayjs from '@/plugins/dayjs'
import { DurationUnitType } from 'dayjs/plugin/duration'

export function formatEta(value: number): string {
const QBIT_MAX_ETA = 8_640_000 // 100 days
export const QBIT_MAX_ETA = 8_640_000 // 100 days
export const INFINITY_SYMBOL = '∞'

export function formatEta(value: number, isForced: boolean = false): string {
const MAX_UNITS = 2 // Will display 2 units max, from highest to lowest

if (value >= QBIT_MAX_ETA) {
return '∞'
if (value >= QBIT_MAX_ETA || (isForced && value === 0)) {
return INFINITY_SYMBOL
}

const minute = 60
Expand Down
4 changes: 3 additions & 1 deletion src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getColorFromName, getRatioColor, getTorrentStateColor, getTorrentStateValue } from './colors'
import comparators, { Comparator } from './comparators'
import { formatDataValue, formatDataUnit, formatData } from './data'
import { formatEta, formatTimeMs, formatTimeSec, formatDuration } from './datetime'
import { QBIT_MAX_ETA, INFINITY_SYMBOL, formatEta, formatTimeMs, formatTimeSec, formatDuration } from './datetime'
import { toPrecision, formatPercent } from './number'
import { basename } from './path'
import { formatSpeedValue, formatSpeedUnit, formatSpeed } from './speed'
Expand All @@ -17,6 +17,8 @@ export {
formatDataValue,
formatDataUnit,
formatData,
QBIT_MAX_ETA,
INFINITY_SYMBOL,
formatEta,
formatTimeMs,
formatTimeSec,
Expand Down
3 changes: 2 additions & 1 deletion src/services/qbit/MockProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
TorrentState
} from '@/constants/qbit'
import { ContentLayout, ProxyType, ResumeDataStorageType, StopCondition, TorrentContentRemoveOption } from '@/constants/qbit/AppPreferences'
import { QBIT_MAX_ETA } from '@/helpers'
import type {
ApplicationVersion,
AppPreferences,
Expand Down Expand Up @@ -95,7 +96,7 @@ export default class MockProvider implements IProvider {
download_path: faker.system.directoryPath(),
downloaded: completed,
downloaded_session: completed,
eta: faker.number.int({ min: 0, max: 900000 }),
eta: faker.number.int({ min: 0, max: QBIT_MAX_ETA }),
f_l_piece_prio: faker.datatype.boolean(), // [0; 5 Mo/s]
force_start: faker.datatype.boolean(),
has_metadata: true,
Expand Down

0 comments on commit f262eca

Please sign in to comment.