summaryrefslogtreecommitdiff
path: root/apps/web/src/lib/media/upload-toast.ts
blob: e5c5ee2872ce8d401565ee01296fc6780571a405 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import { toast } from "sonner";

export interface MediaUploadToastResult {
	uploadedCount: number;
	assetNames?: string[];
}

function getAssetLabel({ count }: { count: number }): string {
	return count === 1 ? "media asset" : "media assets";
}

function waitForNextPaint(): Promise<void> {
	return new Promise((resolve) => {
		requestAnimationFrame(() => {
			requestAnimationFrame(() => resolve());
		});
	});
}

export async function showMediaUploadToast<T extends MediaUploadToastResult>({
	filesCount,
	promise,
}: {
	filesCount: number;
	promise: Promise<T> | (() => Promise<T>);
}) {
	const run = typeof promise === "function" ? promise : () => promise;
	const toastPromise = toast.promise(async () => {
		await waitForNextPaint();
		return run();
	}, {
		loading: `Uploading ${getAssetLabel({ count: filesCount })}...`,
		success: ({ uploadedCount, assetNames }) => {
			if (uploadedCount === 1) {
				const assetName = assetNames?.[0];
				return assetName
					? `${assetName} has been uploaded`
					: "1 media asset has been uploaded";
			}

			if (uploadedCount > 1) {
				return `${uploadedCount} media assets have been uploaded`;
			}

			return "No media assets were uploaded";
		},
		error: `Failed to upload ${getAssetLabel({ count: filesCount })}`,
	});

	return toastPromise.unwrap();
}