feat: integrate Sentry for error tracking and enhance user notifications

- Added Sentry integration for error tracking across various components, including error boundaries and user actions.
- Updated global error handling to capture exceptions and provide detailed feedback to users.
- Enhanced user notifications with toast messages for actions such as credit management, image generation, and canvas exports.
- Improved user experience by displaying relevant messages during interactions, ensuring better visibility of system states and errors.
This commit is contained in:
Matthias
2026-03-27 18:14:04 +01:00
parent 5da0204163
commit 2f89465e82
35 changed files with 2822 additions and 186 deletions

View File

@@ -7,6 +7,8 @@ import JSZip from "jszip";
import { Archive, Loader2 } from "lucide-react";
import { api } from "@/convex/_generated/api";
import type { Id } from "@/convex/_generated/dataModel";
import { toast } from "@/lib/toast";
import { msg } from "@/lib/toast-messages";
interface ExportButtonProps {
canvasName?: string;
@@ -24,12 +26,14 @@ export function ExportButton({ canvasName = "canvas" }: ExportButtonProps) {
setIsExporting(true);
setError(null);
try {
const NO_FRAMES = "NO_FRAMES";
const runExport = async () => {
const nodes = getNodes();
const frameNodes = nodes.filter((node) => node.type === "frame");
if (frameNodes.length === 0) {
throw new Error("No frames on canvas - add a Frame node first");
throw new Error(NO_FRAMES);
}
const zip = new JSZip();
@@ -64,8 +68,36 @@ export function ExportButton({ canvasName = "canvas" }: ExportButtonProps) {
anchor.click();
URL.revokeObjectURL(url);
};
try {
await toast.promise(runExport(), {
loading: msg.export.exportingFrames.title,
success: msg.export.zipReady.title,
error: (err) => {
const m = err instanceof Error ? err.message : "";
if (m === NO_FRAMES) return msg.export.noFramesOnCanvas.title;
if (m.includes("No images found")) return msg.export.frameEmpty.title;
return msg.export.exportFailed.title;
},
description: {
error: (err) => {
const m = err instanceof Error ? err.message : "";
if (m === NO_FRAMES) return msg.export.noFramesOnCanvas.desc;
if (m.includes("No images found")) return msg.export.frameEmpty.desc;
return m || undefined;
},
},
});
} catch (err) {
setError(err instanceof Error ? err.message : "Export failed");
const m = err instanceof Error ? err.message : "";
if (m === NO_FRAMES) {
setError(msg.export.noFramesOnCanvas.desc);
} else if (m.includes("No images found")) {
setError(msg.export.frameEmpty.desc);
} else {
setError(m || msg.export.exportFailed.title);
}
} finally {
setIsExporting(false);
setProgress(null);