Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/pages/popup/components/Footer/DurationSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const cvt2Opt = (value: PopupDuration, n?: string | number): CascaderOption => (

const options = (reverse?: boolean): CascaderOption[] => {
const result: CascaderOption[] = [
...(['today', 'thisWeek', 'thisMonth', 'yesterday'] satisfies PopupDuration[]).map(cvt2Opt),
...(['today', 'yesterday', 'thisWeek', 'thisMonth'] satisfies PopupDuration[]).map(cvt2Opt),
{
...cvt2Opt('lastDays', 'X'),
children: [
Expand Down
38 changes: 30 additions & 8 deletions src/pages/popup/components/Percentage/chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,34 @@ function formatTotalStr(rows: timer.stat.Row[], type: timer.core.Dimension | und
}

function calculateSubTitleText(result: PercentageResult): string {
let { date, dataDate, rows, query: { dimension } = {} } = result
let { date, dataDate, rows, query: { dimension, duration } = {}, dateLength } = result
const dateStr = dataDate ? formatDateStr(date, dataDate) : ''
const totalStr = formatTotalStr(rows, dimension)
let parts = [totalStr, dateStr].filter(str => !!str)

// Calculate average per day
let averageStr = ''
// Don't show averages for single-day durations (today/yesterday)
const isSingleDay = duration === 'today' || duration === 'yesterday'

if (dateLength && dateLength > 0 && !isSingleDay) { // Changed: removed dimension check
if (dimension === 'focus') {
// Average time per day
const total = sum(rows.map(r => r?.focus ?? 0))
const averagePerDay = total / dateLength
const averageTime = formatPeriodCommon(averagePerDay)
averageStr = '(' + t(msg => msg.content.percentage.averageTime, { value: averageTime }) + ')'
} else if (dimension === 'time') {
// Average visits per day
const totalCount = sum(rows.map(r => r.time ?? 0))
const averagePerDay = totalCount / dateLength
const averageCount = averagePerDay.toFixed(1)
averageStr = '(' + t(msg => msg.content.percentage.averageCount, { value: averageCount }) + ')'
}
}

let parts = [totalStr, dateStr, averageStr].filter(str => !!str)
isRtl() && (parts = parts.reverse())
return parts.join(' @ ')
return parts.join(' ')
}

export function generateTitleOption(result: PercentageResult, suffix?: string): TitleComponentOption {
Expand Down Expand Up @@ -265,25 +287,25 @@ export function formatTooltip({ query, dateLength }: PercentageResult, params: T
const format = (Array.isArray(params) ? params[0] : params)
const { name, value, percent, data } = format ?? {}
const { row } = data as PieSeriesItemOption
const { dimension } = query
const { dimension, duration } = query
const itemValue = typeof value === 'number' ? value as number : 0

let valueLine = dimension === 'time' ? itemValue : formatPeriodCommon(itemValue)
// Display percent only when query focus time
dimension === 'focus' && (valueLine += ` (${percent}%)`)

let nameLine = name
let averageLine: string | undefined = undefined
if (!isOther(row)) {
if (isSite(row)) {
const { siteKey: { host } } = row
nameLine = generateSiteLabel(host, name)
}
if (dateLength && dateLength > 1) {
// Don't show averages for single-day durations (today/yesterday)
const isSingleDay = duration === 'today' || duration === 'yesterday'

if (dateLength && dateLength > 1 && !isSingleDay) { // Changed: simplified condition
averageLine = calculateAverageText(dimension, itemValue / dateLength)
}
}

return [nameLine, valueLine, averageLine].filter(l => !!l).join('<br />')
}

Expand Down
14 changes: 12 additions & 2 deletions src/pages/popup/components/Percentage/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,20 @@ export const doQuery = async (query: PopupQuery, option: PopupOption): Promise<P
const [rows, date] = await queryRows(query)
const groups = await listAllGroups()

const dataDate = findDateRange(rows)

// Count actual unique days with data
const allDatesSet = new Set<string>()
rows?.forEach(row => {
const dates = findAllDates(row)
dates.forEach(d => allDatesSet.add(d))
})
const dateLength = allDatesSet.size > 0 ? allDatesSet.size : (date instanceof Array ? getDayLength(date[0], date[1] ?? new Date()) : 1)

return {
query, rows,
date, dataDate: findDateRange(rows),
dateLength: date instanceof Array ? getDayLength(date[0], date[1] ?? new Date()) : 1,
date, dataDate,
dateLength,
displaySiteName,
chartTitle: t(msg => msg.content.percentage.title[query?.duration], { n: query?.durationNum }),
itemCount,
Expand Down
16 changes: 8 additions & 8 deletions src/util/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,15 @@ export function formatPeriod(milliseconds: number, message: Record<'dayMsg' | 'h
*/
export function formatPeriodCommon(milliseconds: number): string {
const defaultMessage = isRtl() ? {
dayMsg: 's {second} m {minute} h {hour} d',
hourMsg: 's {second} m {minute} h {hour}',
minuteMsg: 's {second} m {minute}',
secondMsg: 's {second}',
dayMsg: 's{second} m{minute} h{hour} d',
hourMsg: 's{second} m{minute} h{hour}',
minuteMsg: 's{second} m{minute}',
secondMsg: 's{second}',
} : {
dayMsg: '{day} d {hour} h {minute} m {second} s',
hourMsg: '{hour} h {minute} m {second} s',
minuteMsg: '{minute} m {second} s',
secondMsg: '{second} s',
dayMsg: '{day}d {hour}h {minute}m {second}s',
hourMsg: '{hour}h {minute}m {second}s',
minuteMsg: '{minute}m {second}s',
secondMsg: '{second}s',
}
return formatPeriod(milliseconds, defaultMessage)
}
Expand Down
6 changes: 3 additions & 3 deletions test/util/time.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ test('format', () => {
}
expect(formatPeriod(86400 * 1000, msg)).toEqual('1天0时0分0秒')
expect(formatPeriod(3666 * 1000, msg)).toEqual('1时1分6秒')
expect(formatPeriodCommon(86400 * 1000)).toEqual('1 d 0 h 0 m 0 s')
expect(formatPeriodCommon(3666 * 1000)).toEqual('1 h 1 m 6 s')
expect(formatPeriodCommon(1)).toEqual('0 s')
expect(formatPeriodCommon(86400 * 1000)).toEqual('1d 0h 0m 0s')
expect(formatPeriodCommon(3666 * 1000)).toEqual('1h 1m 6s')
expect(formatPeriodCommon(1)).toEqual('0s')
})

test('days ago', () => {
Expand Down