feat: annotation UX overhaul, animated packing, toolbar redesign

- PinOverlay: zero-allocation rendering with in-place Graphics/Text updates,
  fix WebGL texture crash (addressModeU null) from orphaned Text objects
- Pins always visible on media, track during drag via updatePositions() fast path
- Replace eraser with Review mode in toolbar tool group (orange gradient)
- Add tool instruction hints bar below toolbar (context-sensitive per tool)
- Feedback panel: glassmorphism, improved ThreadDetail/CommentItem/ThreadListItem
- Timestamps: relative with "ago" suffix, full date on hover tooltip
- De-emphasize pin numbers, show status text in thread list
- Animated arrangement transitions (easeOutCubic, 320ms) for pack/grid/row/column
- Disable snap guides (user requested)
- Paste now selects newly created items
- Remove eraser keyboard shortcuts, remap tool shortcuts
- Orphaned thread cleanup: safe destroy check for deleted media pins
This commit is contained in:
Hiren Kangad
2026-03-11 01:53:56 +05:30
parent ed8424d9a1
commit fc2d9df741
16 changed files with 611 additions and 360 deletions
+19 -5
View File
@@ -1,11 +1,25 @@
export function relativeTime(iso: string): string {
const diff = Date.now() - new Date(iso).getTime();
const date = new Date(iso);
const diff = Date.now() - date.getTime();
const mins = Math.floor(diff / 60000);
if (mins < 1) return 'now';
if (mins < 60) return `${mins}m`;
if (mins < 60) return `${mins}m ago`;
const hrs = Math.floor(mins / 60);
if (hrs < 24) return `${hrs}h`;
if (hrs < 24) return `${hrs}h ago`;
const days = Math.floor(hrs / 24);
if (days < 7) return `${days}d`;
return new Date(iso).toLocaleDateString();
if (days < 7) return `${days}d ago`;
// Show date for older comments
return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
}
/** Full timestamp for tooltip hover */
export function fullTimestamp(iso: string): string {
const date = new Date(iso);
return date.toLocaleString(undefined, {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
});
}