feat: Implement a global upload dialog and refactor the upload UI/UX, including manifest size tracking.

This commit is contained in:
2026-02-27 03:49:54 +07:00
parent ff1d4902bc
commit a5b4028bc8
19 changed files with 538 additions and 432 deletions

View File

@@ -52,46 +52,45 @@ export function getImageAspectRatio(url: string): Promise<AspectInfo> {
export const formatBytes = (bytes?: number) => {
if (!bytes) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
if (!bytes) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
export const formatDuration = (seconds?: number) => {
if (!seconds) return '0:00';
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = Math.floor(seconds % 60);
if (!seconds) return '0:00';
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = Math.floor(seconds % 60);
if (h > 0) {
return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
}
return `${m}:${s.toString().padStart(2, '0')}`;
if (h > 0) {
return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
}
return `${m}:${s.toString().padStart(2, '0')}`;
};
export const formatDate = (dateString?: string) => {
if (!dateString) return '';
return new Date(dateString).toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
export const formatDate = (dateString: string = "", dateOnly: boolean = false) => {
if (!dateString) return '';
return new Date(dateString).toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
...(dateOnly ? {} : { hour: '2-digit', minute: '2-digit' })
});
};
export const getStatusSeverity = (status: string = "") => {
switch (status) {
case 'success':
case 'ready':
return 'success';
case 'failed':
return 'danger';
case 'pending':
return 'warn';
default:
return 'info';
}
switch (status) {
case 'success':
case 'ready':
return 'success';
case 'failed':
return 'danger';
case 'pending':
return 'warn';
default:
return 'info';
}
};