feat: add core domain types for Photo Gallery SDK including media items, albums, and annotations
This commit is contained in:
+76
@@ -0,0 +1,76 @@
|
||||
/** Formatting helpers for dates, sizes and durations. */
|
||||
|
||||
const MONTHS = [
|
||||
'January', 'February', 'March', 'April', 'May', 'June',
|
||||
'July', 'August', 'September', 'October', 'November', 'December',
|
||||
];
|
||||
|
||||
export function formatBytes(bytes?: number): string {
|
||||
if (!bytes || bytes <= 0) return '—';
|
||||
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
const i = Math.min(units.length - 1, Math.floor(Math.log(bytes) / Math.log(1024)));
|
||||
const value = bytes / Math.pow(1024, i);
|
||||
return `${value.toFixed(value >= 10 || i === 0 ? 0 : 1)} ${units[i]}`;
|
||||
}
|
||||
|
||||
export function formatDuration(seconds?: number): string {
|
||||
if (!seconds || seconds < 0) return '';
|
||||
const s = Math.floor(seconds % 60);
|
||||
const m = Math.floor((seconds / 60) % 60);
|
||||
const h = Math.floor(seconds / 3600);
|
||||
const pad = (n: number) => n.toString().padStart(2, '0');
|
||||
return h > 0 ? `${h}:${pad(m)}:${pad(s)}` : `${m}:${pad(s)}`;
|
||||
}
|
||||
|
||||
export function formatDate(ms: number): string {
|
||||
const d = new Date(ms);
|
||||
return `${MONTHS[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`;
|
||||
}
|
||||
|
||||
export function formatDay(ms: number): string {
|
||||
const d = new Date(ms);
|
||||
const today = new Date();
|
||||
const yesterday = new Date(today);
|
||||
yesterday.setDate(today.getDate() - 1);
|
||||
const sameDay = (a: Date, b: Date) =>
|
||||
a.getFullYear() === b.getFullYear() &&
|
||||
a.getMonth() === b.getMonth() &&
|
||||
a.getDate() === b.getDate();
|
||||
if (sameDay(d, today)) return 'Today';
|
||||
if (sameDay(d, yesterday)) return 'Yesterday';
|
||||
const weekday = d.toLocaleDateString(undefined, { weekday: 'long' });
|
||||
return `${weekday}, ${MONTHS[d.getMonth()]} ${d.getDate()}`;
|
||||
}
|
||||
|
||||
export function formatMonth(ms: number): string {
|
||||
const d = new Date(ms);
|
||||
return `${MONTHS[d.getMonth()]} ${d.getFullYear()}`;
|
||||
}
|
||||
|
||||
export function formatYear(ms: number): string {
|
||||
return new Date(ms).getFullYear().toString();
|
||||
}
|
||||
|
||||
export function formatTime(ms: number): string {
|
||||
return new Date(ms).toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
|
||||
}
|
||||
|
||||
export function relativeTime(ms: number): string {
|
||||
const diff = Date.now() - ms;
|
||||
const day = 24 * 60 * 60 * 1000;
|
||||
if (diff < 0) return 'in the future';
|
||||
if (diff < day) return 'today';
|
||||
const days = Math.floor(diff / day);
|
||||
if (days === 1) return 'yesterday';
|
||||
if (days < 30) return `${days} days ago`;
|
||||
const months = Math.floor(days / 30);
|
||||
if (months < 12) return `${months} month${months > 1 ? 's' : ''} ago`;
|
||||
const years = Math.floor(days / 365);
|
||||
return `${years} year${years > 1 ? 's' : ''} ago`;
|
||||
}
|
||||
|
||||
/** Days remaining before a trashed item is permanently removed. */
|
||||
export function daysUntilPermanentDelete(deletedAt: number, retentionMs: number): number {
|
||||
const remaining = deletedAt + retentionMs - Date.now();
|
||||
return Math.max(0, Math.ceil(remaining / (24 * 60 * 60 * 1000)));
|
||||
}
|
||||
Reference in New Issue
Block a user