mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-17 19:36:28 +02:00
Consolidate duplicate utility functions into shared modules
Extract repeated helper functions from components into shared utils (colors.ts, date.ts, file.ts) to reduce duplication: - isLightColor, parseFilamentColor, hexToColorName → utils/colors.ts - formatMediaTime, formatDurationFromHours → utils/date.ts - formatFileSize guard hardened for NaN/negative → utils/file.ts - formatBytes (ToastContext), formatTime (Timelapse*) deduplicated Functions with subtly different behavior are intentionally kept local (formatFilament, formatStorageSize, formatBytes, formatUptime, formatDateTime, formatDate, formatTimeAgo) to preserve exact UI output.
This commit is contained in:
@@ -83,6 +83,9 @@ export function hexToColorName(hex: string | null | undefined): string {
|
||||
if (l > 0.6) return 'Light Gray';
|
||||
return 'Gray';
|
||||
}
|
||||
// Brown is orange/yellow hue with lower lightness
|
||||
if (h >= 15 && h < 45 && l < 0.45) return 'Brown';
|
||||
if (h >= 45 && h < 70 && l < 0.40) return 'Brown';
|
||||
if (h < 15 || h >= 345) return 'Red';
|
||||
if (h < 45) return 'Orange';
|
||||
if (h < 70) return 'Yellow';
|
||||
@@ -125,3 +128,30 @@ export function resolveSpoolColorName(colorName: string | null, rgba: string | n
|
||||
// Return null (displayed as "-") — better than showing a code
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an RGBA hex string (e.g., "FF0000FF") to a CSS rgba() color.
|
||||
* Returns null for empty, all-zero, or fully transparent colors.
|
||||
*/
|
||||
export function parseFilamentColor(rgba: string): string | null {
|
||||
if (!rgba || rgba === '00000000' || rgba.length < 6) return null;
|
||||
const r = rgba.slice(0, 2);
|
||||
const g = rgba.slice(2, 4);
|
||||
const b = rgba.slice(4, 6);
|
||||
const a = rgba.length >= 8 ? parseInt(rgba.slice(6, 8), 16) / 255 : 1;
|
||||
if (a === 0) return null;
|
||||
return `rgba(${parseInt(r, 16)}, ${parseInt(g, 16)}, ${parseInt(b, 16)}, ${a})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a hex color is light (for choosing text contrast).
|
||||
* Uses luminance formula: 0.299*R + 0.587*G + 0.114*B.
|
||||
*/
|
||||
export function isLightColor(hex: string | null): boolean {
|
||||
if (!hex || hex.length < 6) return false;
|
||||
const cleanHex = hex.replace('#', '');
|
||||
const r = parseInt(cleanHex.slice(0, 2), 16);
|
||||
const g = parseInt(cleanHex.slice(2, 4), 16);
|
||||
const b = parseInt(cleanHex.slice(4, 6), 16);
|
||||
return (0.299 * r + 0.587 * g + 0.114 * b) / 255 > 0.6;
|
||||
}
|
||||
|
||||
@@ -418,3 +418,28 @@ export function formatRelativeTime(
|
||||
// Older than 7 days
|
||||
return formatDateTime(dateStr, timeFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format seconds as MM:SS for media/video player display.
|
||||
*
|
||||
* @param seconds - Total seconds
|
||||
* @returns Formatted string (e.g., "2:05", "0:30")
|
||||
*/
|
||||
export function formatMediaTime(seconds: number): string {
|
||||
const mins = Math.floor(seconds / 60);
|
||||
const secs = Math.floor(seconds % 60);
|
||||
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a duration given in hours to a human-readable string.
|
||||
*
|
||||
* @param hours - Duration in hours (e.g., 2.5)
|
||||
* @returns Formatted string (e.g., "2h 30m", "45m", "3h")
|
||||
*/
|
||||
export function formatDurationFromHours(hours: number): string {
|
||||
if (hours < 1) return `${Math.round(hours * 60)}m`;
|
||||
const h = Math.floor(hours);
|
||||
const m = Math.round((hours - h) * 60);
|
||||
return m > 0 ? `${h}h ${m}m` : `${h}h`;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* @returns A formatted string with the appropriate unit (B, KB, MB, GB, or TB).
|
||||
*/
|
||||
export function formatFileSize(bytes: number): string {
|
||||
if (bytes === 0) return '0 B';
|
||||
if (!Number.isFinite(bytes) || bytes <= 0) return '0 B';
|
||||
|
||||
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
const k = 1024;
|
||||
|
||||
Reference in New Issue
Block a user