Skip to content

feat: create version history dropdown #71

Closed
@nullcoder

Description

@nullcoder

Description

Create a dropdown component to select and view different versions of a gist, integrated with the version history system.

Requirements

  • Dropdown showing version list with numbers and timestamps
  • Current version clearly highlighted
  • Human-readable timestamps (e.g., "2 hours ago", "Dec 5 at 3:45 PM")
  • Load selected version on change
  • Show version metadata (who edited, if PIN was used)
  • Maximum 50 versions as per spec
  • Reverse chronological order (newest first)
  • Loading state while fetching version
  • Error handling for failed loads
  • Mobile-friendly dropdown UI

Acceptance Criteria

  • Lists all available versions (up to 50)
  • Current version is highlighted and marked
  • Selection triggers version load with loading state
  • Timestamps are human-readable and relative
  • Shows version number (e.g., "Version 3 of 12")
  • Dropdown is keyboard navigable
  • Works well on mobile devices
  • Shows helpful empty state if only 1 version
  • Indicates if version was PIN-protected edit
  • Smooth transition between versions

UI Structure

Version: 3 of 12 [▼]
┌─────────────────────────────────────┐
│ ✓ Version 3 (current)               │
│   2 hours ago                       │
├─────────────────────────────────────┤
│   Version 2                         │
│   Yesterday at 4:32 PM              │
├─────────────────────────────────────┤
│   Version 1 (original)              │
│   Dec 5 at 10:15 AM                │
└─────────────────────────────────────┘

Props Interface

interface VersionSelectorProps {
  currentVersion: number;
  versions: Array<{
    version: number;
    created_at: string;
    size: number;
    file_count: number;
    edited_with_pin?: boolean;
  }>;
  onVersionChange: (version: number) => void;
  loading?: boolean;
  disabled?: boolean;
}

Technical Implementation

// Format relative timestamps
function formatVersionTime(timestamp: string): string {
  const date = new Date(timestamp);
  const now = new Date();
  const diffMs = now.getTime() - date.getTime();
  
  // Use relative time for recent versions
  if (diffMs < 24 * 60 * 60 * 1000) {
    return formatRelative(date); // "2 hours ago"
  }
  
  // Use absolute time for older versions
  return format(date, 'MMM d at h:mm a'); // "Dec 5 at 3:45 PM"
}

Version History Storage

Per the spec, versions are stored at:

versions/{gist-id}/{timestamp}.bin

The component should:

  1. Display available versions from metadata
  2. Fetch specific version blob when selected
  3. Decrypt with the same key (versions share encryption key)
  4. Update the UI with the historical content

Technical Notes

  • Use shadcn/ui Select component
  • Implement with React hooks for state management
  • Consider caching recently viewed versions
  • Show loading spinner during version fetch
  • Handle errors gracefully (toast notification)
  • Ensure smooth UX when switching versions
  • Consider showing diff indicator in future enhancement

Accessibility

  • Announce version changes to screen readers
  • Keyboard navigation with arrow keys
  • Clear labels for current vs. historical versions
  • Escape key to close dropdown

Related

  • Used by feat: create gist viewer component #61 (GistViewer component)
  • Works with version history system from spec
  • Part of Phase 4 UI Components
  • Integrates with storage structure defined in SPEC.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew feature implementationpriority: lowNice to haveuiUser interface and components

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions