mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 09:36:08 +00:00
feat(storage): point a full trial account at the upgrade rather than at nothing
Being told "storage limit exceeded" when the limit is the free trial's three gigabytes is a dead end. The account is not full because it stores a lot; it is capped because it has not subscribed, and deleting files buys back very little. The refusal now says which ceiling it is and carries its own error code, so the toast can offer a link to the billing settings on the trial ceiling and stay quiet on the paid one, where subscribing changes nothing. The code had to survive the trip to the toast, which meant the upload helpers throwing something that carries it rather than a bare Error. Two places were dropping the server's message on the floor entirely: adding a version reported "Failed to initialize upload" whatever the server said, and every asset upload in the pane rewrote its own failure text.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import * as tus from 'tus-js-client';
|
||||
import { toast } from 'sonner';
|
||||
import { toastApiError } from '@/lib/client/api-error';
|
||||
import {
|
||||
Download,
|
||||
FileVideo,
|
||||
@@ -56,6 +57,7 @@ function formatTime(seconds: number): string {
|
||||
type UploadAudioResponse = {
|
||||
data?: { url?: string; reservationId?: string | null };
|
||||
error?: string;
|
||||
code?: string;
|
||||
};
|
||||
|
||||
function getAudioUploadValidationError(file: Blob): string | null {
|
||||
@@ -369,10 +371,11 @@ export const AssetsPane = memo(function AssetsPane({
|
||||
const uploadPayload = (await uploadRes.json().catch(() => null)) as {
|
||||
data?: { url?: string; reservationId?: string | null };
|
||||
error?: string;
|
||||
code?: string;
|
||||
} | null;
|
||||
const uploadedImageUrl = uploadPayload?.data?.url;
|
||||
if (!uploadRes.ok || !uploadedImageUrl) {
|
||||
toast.error(`${file.name}: ${uploadPayload?.error || 'Failed to upload image'}`);
|
||||
toastApiError(uploadPayload, 'Failed to upload image', { prefix: file.name });
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -385,7 +388,7 @@ export const AssetsPane = memo(function AssetsPane({
|
||||
return !!created;
|
||||
} catch (error) {
|
||||
console.error('Failed to upload image asset:', error);
|
||||
toast.error(`${file.name}: Failed to upload image`);
|
||||
toastApiError(error, 'Failed to upload image', { prefix: file.name });
|
||||
return false;
|
||||
}
|
||||
},
|
||||
@@ -523,10 +526,11 @@ export const AssetsPane = memo(function AssetsPane({
|
||||
uploadToken: string;
|
||||
};
|
||||
error?: string;
|
||||
code?: string;
|
||||
} | null;
|
||||
|
||||
if (!initRes.ok || !initPayload?.data) {
|
||||
toast.error(`${file.name}: ${initPayload?.error || 'Failed to initialize Bunny upload'}`);
|
||||
toastApiError(initPayload, 'Failed to initialize Bunny upload', { prefix: file.name });
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -578,7 +582,7 @@ export const AssetsPane = memo(function AssetsPane({
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to upload Bunny asset:', error);
|
||||
toast.error(`${file.name}: Failed to upload Bunny video`);
|
||||
toastApiError(error, 'Failed to upload Bunny video', { prefix: file.name });
|
||||
if (uploadedVideoId && uploadToken) {
|
||||
await fetch(`/api/videos/${videoId}/assets/bunny-init`, {
|
||||
method: 'DELETE',
|
||||
@@ -631,7 +635,7 @@ export const AssetsPane = memo(function AssetsPane({
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to upload R2 asset video:', error);
|
||||
toast.error(`${file.name}: Failed to upload video`);
|
||||
toastApiError(error, 'Failed to upload video', { prefix: file.name });
|
||||
return false;
|
||||
} finally {
|
||||
setIsUploadingBunny(false);
|
||||
@@ -801,12 +805,12 @@ export const AssetsPane = memo(function AssetsPane({
|
||||
const uploadPayload = await readUploadAudioResponse(uploadRes);
|
||||
const uploadedUrl = uploadPayload?.data?.url;
|
||||
if (!uploadRes.ok || !uploadedUrl) {
|
||||
toast.error(
|
||||
`${fileName}: ${
|
||||
uploadPayload?.error ||
|
||||
(uploadRes.status === 413 ? MAX_AUDIO_UPLOAD_SIZE_MESSAGE : null) ||
|
||||
'Failed to upload voice recording'
|
||||
}`
|
||||
toastApiError(
|
||||
uploadPayload,
|
||||
uploadRes.status === 413
|
||||
? MAX_AUDIO_UPLOAD_SIZE_MESSAGE
|
||||
: 'Failed to upload voice recording',
|
||||
{ prefix: fileName }
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@@ -821,7 +825,7 @@ export const AssetsPane = memo(function AssetsPane({
|
||||
return !!created;
|
||||
} catch (error) {
|
||||
console.error('Failed to upload voice asset:', error);
|
||||
toast.error(`${fileName}: Failed to upload voice recording`);
|
||||
toastApiError(error, 'Failed to upload voice recording', { prefix: fileName });
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user