mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
Show relative time in resume picker
This commit is contained in:
@@ -3,6 +3,7 @@ import { Box, Text, useInput, useStdout } from 'ink'
|
||||
import type { ResumableSession } from '@hapi/protocol'
|
||||
import {
|
||||
filterResumeSessions,
|
||||
formatResumeSessionRelativeTime,
|
||||
getResumeSessionName,
|
||||
getResumeSessionState,
|
||||
normalizeScrollOffset,
|
||||
@@ -41,7 +42,8 @@ function truncateText(value: string, maxLength: number): string {
|
||||
|
||||
function formatSessionLine(session: ResumableSession, width: number): string {
|
||||
const state = getResumeSessionState(session)
|
||||
const prefix = `${session.flavor.padEnd(8)} ${state.padEnd(8)} `
|
||||
const time = formatResumeSessionRelativeTime(session.updatedAt).padStart(10)
|
||||
const prefix = `${time} ${session.flavor.padEnd(8)} ${state.padEnd(8)} `
|
||||
const directoryBudget = Math.max(16, Math.floor(width * 0.35))
|
||||
const nameBudget = Math.max(12, width - prefix.length - directoryBudget - 2)
|
||||
const name = truncateText(getResumeSessionName(session), nameBudget)
|
||||
|
||||
@@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest'
|
||||
import type { ResumableSession } from '@hapi/protocol'
|
||||
import {
|
||||
filterResumeSessions,
|
||||
formatResumeSessionRelativeTime,
|
||||
reducePickerState,
|
||||
type PickerState
|
||||
} from './resumeSessionPickerState'
|
||||
@@ -22,6 +23,17 @@ function session(overrides: Partial<ResumableSession>): ResumableSession {
|
||||
}
|
||||
|
||||
describe('resumeSessionPickerState', () => {
|
||||
it('formats updatedAt as relative time', () => {
|
||||
const now = 1_700_000_000_000
|
||||
|
||||
expect(formatResumeSessionRelativeTime(now - 10_000, now)).toBe('now')
|
||||
expect(formatResumeSessionRelativeTime(now - 5 * 60_000, now)).toBe('5m ago')
|
||||
expect(formatResumeSessionRelativeTime(now - 3 * 60 * 60_000, now)).toBe('3h ago')
|
||||
expect(formatResumeSessionRelativeTime(now - 2 * 24 * 60 * 60_000, now)).toBe('2d ago')
|
||||
expect(formatResumeSessionRelativeTime(Math.floor((now - 5 * 60_000) / 1000), now)).toBe('5m ago')
|
||||
expect(formatResumeSessionRelativeTime(NaN, now)).toBe('unknown')
|
||||
})
|
||||
|
||||
it('filters sessions by searchable fields case-insensitively', () => {
|
||||
const sessions = [
|
||||
session({
|
||||
|
||||
@@ -25,6 +25,25 @@ export function getResumeSessionState(session: ResumableSession): string {
|
||||
return session.controlledByUser ? 'local' : 'remote'
|
||||
}
|
||||
|
||||
export function formatResumeSessionRelativeTime(value: number, now: number = Date.now()): string {
|
||||
const ms = value < 1_000_000_000_000 ? value * 1000 : value
|
||||
if (!Number.isFinite(ms)) return 'unknown'
|
||||
|
||||
const delta = Math.max(0, now - ms)
|
||||
if (delta < 60_000) return 'now'
|
||||
|
||||
const minutes = Math.floor(delta / 60_000)
|
||||
if (minutes < 60) return `${minutes}m ago`
|
||||
|
||||
const hours = Math.floor(minutes / 60)
|
||||
if (hours < 24) return `${hours}h ago`
|
||||
|
||||
const days = Math.floor(hours / 24)
|
||||
if (days < 7) return `${days}d ago`
|
||||
|
||||
return new Date(ms).toLocaleDateString()
|
||||
}
|
||||
|
||||
export function filterResumeSessions(
|
||||
sessions: ResumableSession[],
|
||||
query: string
|
||||
|
||||
Reference in New Issue
Block a user