ميزه: إضافة ميزات جديدة لتحرير PDF، OCR، وإزالة الخلفية مع تفعيل خيارات في ملف البيئة

This commit is contained in:
Your Name
2026-03-08 22:51:50 +02:00
parent d7f6228d7f
commit 0a0c069a58
16 changed files with 242 additions and 62 deletions

View File

@@ -0,0 +1,48 @@
import { Component, type ReactNode } from 'react';
import { AlertTriangle } from 'lucide-react';
interface Props {
children: ReactNode;
fallbackMessage?: string;
}
interface State {
hasError: boolean;
}
export default class ErrorBoundary extends Component<Props, State> {
state: State = { hasError: false };
static getDerivedStateFromError(): State {
return { hasError: true };
}
handleReset = () => {
this.setState({ hasError: false });
};
render() {
if (this.state.hasError) {
return (
<div className="mx-auto max-w-lg py-16 text-center">
<div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-red-100 dark:bg-red-900/30">
<AlertTriangle className="h-8 w-8 text-red-600 dark:text-red-400" />
</div>
<h2 className="mb-2 text-xl font-semibold text-slate-800 dark:text-slate-200">
{this.props.fallbackMessage || 'Something went wrong'}
</h2>
<p className="mb-6 text-sm text-slate-500 dark:text-slate-400">
An unexpected error occurred. Please try again.
</p>
<button
onClick={this.handleReset}
className="rounded-lg bg-primary-600 px-6 py-2 text-sm font-medium text-white hover:bg-primary-700 transition-colors"
>
Try Again
</button>
</div>
);
}
return this.props.children;
}
}

View File

@@ -43,7 +43,7 @@ export default function QrCodeGenerator() {
setError(null);
};
const downloadUrl = result?.download_url ? `/api${result.download_url}` : null;
const downloadUrl = result?.download_url || null;
const schema = generateToolSchema({
name: t('tools.qrCode.title'),

View File

@@ -143,6 +143,17 @@ export default function RemoveBackground() {
</div>
)}
{phase === 'done' && !result && taskError && (
<div className="space-y-4">
<div className="rounded-xl bg-red-50 p-4 text-red-600 dark:bg-red-900/20 dark:text-red-400">
{taskError}
</div>
<button onClick={handleReset} className="btn-secondary w-full">
{t('common.tryAgain')}
</button>
</div>
)}
<AdSlot slot="bottom-banner" format="horizontal" className="mt-6" />
</div>
</>