Initial commit - realms platform
This commit is contained in:
parent
c590ab6d18
commit
c717c3751c
234 changed files with 74103 additions and 15231 deletions
123
frontend/src/lib/utils/formatters.js
Normal file
123
frontend/src/lib/utils/formatters.js
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* Shared formatting utilities for the frontend
|
||||
*/
|
||||
|
||||
/**
|
||||
* Format seconds to duration string (e.g., "1:23" or "1:23:45")
|
||||
* @param {number} seconds - Duration in seconds
|
||||
* @param {boolean} includeHours - Always include hours for long durations (auto-detected if false)
|
||||
* @returns {string} Formatted duration
|
||||
*/
|
||||
export function formatDuration(seconds, includeHours = false) {
|
||||
if (!seconds) return '0:00';
|
||||
const hrs = Math.floor(seconds / 3600);
|
||||
const mins = Math.floor((seconds % 3600) / 60);
|
||||
const secs = Math.floor(seconds % 60);
|
||||
if (includeHours || hrs > 0) {
|
||||
return `${hrs}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
||||
}
|
||||
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format view/play count with K/M suffix
|
||||
* @param {number} count - The count to format
|
||||
* @param {boolean} includeSuffix - Append " views" to the output
|
||||
* @returns {string} Formatted count (e.g., "1.2K" or "1.2K views")
|
||||
*/
|
||||
export function formatViews(count, includeSuffix = false) {
|
||||
if (count === null || count === undefined) count = 0;
|
||||
const suffix = includeSuffix ? ' views' : '';
|
||||
if (count >= 1000000) return (count / 1000000).toFixed(1) + 'M' + suffix;
|
||||
if (count >= 1000) return (count / 1000).toFixed(1) + 'K' + suffix;
|
||||
return count.toString() + suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format date as relative time (e.g., "5 min ago", "2 days ago")
|
||||
* @param {string|Date} dateStr - Date string or Date object
|
||||
* @param {boolean} short - Use abbreviated format (m, h, d instead of full text)
|
||||
* @returns {string} Relative time string
|
||||
*/
|
||||
export function timeAgo(dateStr, short = false) {
|
||||
const date = new Date(dateStr);
|
||||
const now = new Date();
|
||||
const seconds = Math.floor((now - date) / 1000);
|
||||
|
||||
if (short) {
|
||||
if (seconds < 60) return 'now';
|
||||
if (seconds < 3600) return Math.floor(seconds / 60) + 'm';
|
||||
if (seconds < 86400) return Math.floor(seconds / 3600) + 'h';
|
||||
if (seconds < 604800) return Math.floor(seconds / 86400) + 'd';
|
||||
return date.toLocaleDateString();
|
||||
}
|
||||
|
||||
if (seconds < 60) return 'just now';
|
||||
if (seconds < 3600) return Math.floor(seconds / 60) + ' min ago';
|
||||
if (seconds < 86400) return Math.floor(seconds / 3600) + ' hours ago';
|
||||
if (seconds < 604800) return Math.floor(seconds / 86400) + ' days ago';
|
||||
return date.toLocaleDateString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format bytes to human-readable size
|
||||
* @param {number} bytes - Size in bytes
|
||||
* @returns {string} Formatted size (e.g., "1.5 GB")
|
||||
*/
|
||||
export function formatBytes(bytes) {
|
||||
if (!bytes) return '0 bytes';
|
||||
if (bytes >= 1073741824) return (bytes / 1073741824).toFixed(2) + ' GB';
|
||||
if (bytes >= 1048576) return (bytes / 1048576).toFixed(2) + ' MB';
|
||||
if (bytes >= 1024) return (bytes / 1024).toFixed(2) + ' KB';
|
||||
return bytes + ' bytes';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format bitrate to human-readable format
|
||||
* @param {number} bps - Bitrate in bits per second
|
||||
* @returns {string} Formatted bitrate (e.g., "2.5 Mbps")
|
||||
*/
|
||||
export function formatBitrate(bps) {
|
||||
if (!bps) return '';
|
||||
const kbps = Math.round(bps / 1000);
|
||||
if (kbps >= 1000) return (kbps / 1000).toFixed(1) + ' Mbps';
|
||||
return kbps + ' kbps';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format codec name to human-readable format
|
||||
* @param {string} codec - Raw codec name
|
||||
* @returns {string} Human-readable codec name
|
||||
*/
|
||||
export function formatCodec(codec) {
|
||||
if (!codec) return '';
|
||||
const codecMap = {
|
||||
'h264': 'H.264 (AVC)',
|
||||
'hevc': 'H.265 (HEVC)',
|
||||
'h265': 'H.265 (HEVC)',
|
||||
'vp9': 'VP9',
|
||||
'vp8': 'VP8',
|
||||
'av1': 'AV1',
|
||||
'aac': 'AAC',
|
||||
'mp3': 'MP3',
|
||||
'opus': 'Opus',
|
||||
'vorbis': 'Vorbis',
|
||||
'flac': 'FLAC',
|
||||
'ac3': 'AC-3',
|
||||
'eac3': 'E-AC-3'
|
||||
};
|
||||
return codecMap[codec.toLowerCase()] || codec.toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format date to localized string
|
||||
* @param {string|Date} dateStr - Date string or Date object
|
||||
* @returns {string} Formatted date (e.g., "January 1, 2024")
|
||||
*/
|
||||
export function formatDate(dateStr) {
|
||||
return new Date(dateStr).toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue