Skip to content

Commit e59e68f

Browse files
authored
feat: improve time display and add daily averages (#615)
1 parent 24286f9 commit e59e68f

File tree

5 files changed

+54
-22
lines changed

5 files changed

+54
-22
lines changed

src/pages/popup/components/Footer/DurationSelect.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const cvt2Opt = (value: PopupDuration, n?: string | number): CascaderOption => (
2020

2121
const options = (reverse?: boolean): CascaderOption[] => {
2222
const result: CascaderOption[] = [
23-
...(['today', 'thisWeek', 'thisMonth', 'yesterday'] satisfies PopupDuration[]).map(cvt2Opt),
23+
...(['today', 'yesterday', 'thisWeek', 'thisMonth'] satisfies PopupDuration[]).map(cvt2Opt),
2424
{
2525
...cvt2Opt('lastDays', 'X'),
2626
children: [

src/pages/popup/components/Percentage/chart.ts

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,34 @@ function formatTotalStr(rows: timer.stat.Row[], type: timer.core.Dimension | und
7373
}
7474

7575
function calculateSubTitleText(result: PercentageResult): string {
76-
let { date, dataDate, rows, query: { dimension } = {} } = result
76+
let { date, dataDate, rows, query: { dimension, duration } = {}, dateLength } = result
7777
const dateStr = dataDate ? formatDateStr(date, dataDate) : ''
7878
const totalStr = formatTotalStr(rows, dimension)
79-
let parts = [totalStr, dateStr].filter(str => !!str)
79+
80+
// Calculate average per day
81+
let averageStr = ''
82+
// Don't show averages for single-day durations (today/yesterday)
83+
const isSingleDay = duration === 'today' || duration === 'yesterday'
84+
85+
if (dateLength && dateLength > 0 && !isSingleDay) { // Changed: removed dimension check
86+
if (dimension === 'focus') {
87+
// Average time per day
88+
const total = sum(rows.map(r => r?.focus ?? 0))
89+
const averagePerDay = total / dateLength
90+
const averageTime = formatPeriodCommon(averagePerDay)
91+
averageStr = '(' + t(msg => msg.content.percentage.averageTime, { value: averageTime }) + ')'
92+
} else if (dimension === 'time') {
93+
// Average visits per day
94+
const totalCount = sum(rows.map(r => r.time ?? 0))
95+
const averagePerDay = totalCount / dateLength
96+
const averageCount = averagePerDay.toFixed(1)
97+
averageStr = '(' + t(msg => msg.content.percentage.averageCount, { value: averageCount }) + ')'
98+
}
99+
}
100+
101+
let parts = [totalStr, dateStr, averageStr].filter(str => !!str)
80102
isRtl() && (parts = parts.reverse())
81-
return parts.join(' @ ')
103+
return parts.join(' ')
82104
}
83105

84106
export function generateTitleOption(result: PercentageResult, suffix?: string): TitleComponentOption {
@@ -265,25 +287,25 @@ export function formatTooltip({ query, dateLength }: PercentageResult, params: T
265287
const format = (Array.isArray(params) ? params[0] : params)
266288
const { name, value, percent, data } = format ?? {}
267289
const { row } = data as PieSeriesItemOption
268-
const { dimension } = query
290+
const { dimension, duration } = query
269291
const itemValue = typeof value === 'number' ? value as number : 0
270-
271292
let valueLine = dimension === 'time' ? itemValue : formatPeriodCommon(itemValue)
272293
// Display percent only when query focus time
273294
dimension === 'focus' && (valueLine += ` (${percent}%)`)
274-
275295
let nameLine = name
276296
let averageLine: string | undefined = undefined
277297
if (!isOther(row)) {
278298
if (isSite(row)) {
279299
const { siteKey: { host } } = row
280300
nameLine = generateSiteLabel(host, name)
281301
}
282-
if (dateLength && dateLength > 1) {
302+
// Don't show averages for single-day durations (today/yesterday)
303+
const isSingleDay = duration === 'today' || duration === 'yesterday'
304+
305+
if (dateLength && dateLength > 1 && !isSingleDay) { // Changed: simplified condition
283306
averageLine = calculateAverageText(dimension, itemValue / dateLength)
284307
}
285308
}
286-
287309
return [nameLine, valueLine, averageLine].filter(l => !!l).join('<br />')
288310
}
289311

src/pages/popup/components/Percentage/query.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,20 @@ export const doQuery = async (query: PopupQuery, option: PopupOption): Promise<P
4949
const [rows, date] = await queryRows(query)
5050
const groups = await listAllGroups()
5151

52+
const dataDate = findDateRange(rows)
53+
54+
// Count actual unique days with data
55+
const allDatesSet = new Set<string>()
56+
rows?.forEach(row => {
57+
const dates = findAllDates(row)
58+
dates.forEach(d => allDatesSet.add(d))
59+
})
60+
const dateLength = allDatesSet.size > 0 ? allDatesSet.size : (date instanceof Array ? getDayLength(date[0], date[1] ?? new Date()) : 1)
61+
5262
return {
5363
query, rows,
54-
date, dataDate: findDateRange(rows),
55-
dateLength: date instanceof Array ? getDayLength(date[0], date[1] ?? new Date()) : 1,
64+
date, dataDate,
65+
dateLength,
5666
displaySiteName,
5767
chartTitle: t(msg => msg.content.percentage.title[query?.duration], { n: query?.durationNum }),
5868
itemCount,

src/util/time.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,15 @@ export function formatPeriod(milliseconds: number, message: Record<'dayMsg' | 'h
105105
*/
106106
export function formatPeriodCommon(milliseconds: number): string {
107107
const defaultMessage = isRtl() ? {
108-
dayMsg: 's {second} m {minute} h {hour} d',
109-
hourMsg: 's {second} m {minute} h {hour}',
110-
minuteMsg: 's {second} m {minute}',
111-
secondMsg: 's {second}',
108+
dayMsg: 's{second} m{minute} h{hour} d',
109+
hourMsg: 's{second} m{minute} h{hour}',
110+
minuteMsg: 's{second} m{minute}',
111+
secondMsg: 's{second}',
112112
} : {
113-
dayMsg: '{day} d {hour} h {minute} m {second} s',
114-
hourMsg: '{hour} h {minute} m {second} s',
115-
minuteMsg: '{minute} m {second} s',
116-
secondMsg: '{second} s',
113+
dayMsg: '{day}d {hour}h {minute}m {second}s',
114+
hourMsg: '{hour}h {minute}m {second}s',
115+
minuteMsg: '{minute}m {second}s',
116+
secondMsg: '{second}s',
117117
}
118118
return formatPeriod(milliseconds, defaultMessage)
119119
}

test/util/time.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ test('format', () => {
3838
}
3939
expect(formatPeriod(86400 * 1000, msg)).toEqual('1天0时0分0秒')
4040
expect(formatPeriod(3666 * 1000, msg)).toEqual('1时1分6秒')
41-
expect(formatPeriodCommon(86400 * 1000)).toEqual('1 d 0 h 0 m 0 s')
42-
expect(formatPeriodCommon(3666 * 1000)).toEqual('1 h 1 m 6 s')
43-
expect(formatPeriodCommon(1)).toEqual('0 s')
41+
expect(formatPeriodCommon(86400 * 1000)).toEqual('1d 0h 0m 0s')
42+
expect(formatPeriodCommon(3666 * 1000)).toEqual('1h 1m 6s')
43+
expect(formatPeriodCommon(1)).toEqual('0s')
4444
})
4545

4646
test('days ago', () => {

0 commit comments

Comments
 (0)