- Removed all Grok-related code, API routes, and services - Removed crawl4ai service and meta-crawl client - Simplified Settings to always show cookie inputs for Meta AI - Hid advanced wrapper settings behind collapsible section - Provider selection now only shows Whisk and Meta AI - Fixed unused imports and type definitions
181 lines
10 KiB
TypeScript
181 lines
10 KiB
TypeScript
"use client";
|
|
|
|
import React from 'react';
|
|
import { useStore } from '@/lib/store';
|
|
import { Save, Sparkles, Brain, Settings2 } from 'lucide-react';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
type Provider = 'whisk' | 'meta';
|
|
|
|
const providers: { id: Provider; name: string; icon: any; description: string }[] = [
|
|
{ id: 'whisk', name: 'Google Whisk', icon: Sparkles, description: 'ImageFX / Imagen 3' },
|
|
{ id: 'meta', name: 'Meta AI', icon: Brain, description: 'Imagine / Emu' },
|
|
];
|
|
|
|
export function Settings() {
|
|
const { settings, setSettings } = useStore();
|
|
|
|
// Local state for form fields
|
|
const [provider, setProvider] = React.useState<Provider>(settings.provider || 'whisk');
|
|
const [whiskCookies, setWhiskCookies] = React.useState(settings.whiskCookies || '');
|
|
const [useMetaFreeWrapper, setUseMetaFreeWrapper] = React.useState(settings.useMetaFreeWrapper !== undefined ? settings.useMetaFreeWrapper : true);
|
|
const [metaFreeWrapperUrl, setMetaFreeWrapperUrl] = React.useState(settings.metaFreeWrapperUrl || 'http://localhost:8000');
|
|
const [metaCookies, setMetaCookies] = React.useState(settings.metaCookies || '');
|
|
const [facebookCookies, setFacebookCookies] = React.useState(settings.facebookCookies || '');
|
|
const [saved, setSaved] = React.useState(false);
|
|
|
|
const handleSave = () => {
|
|
setSettings({
|
|
provider,
|
|
whiskCookies,
|
|
useMetaFreeWrapper,
|
|
metaFreeWrapperUrl,
|
|
metaCookies,
|
|
facebookCookies
|
|
});
|
|
setSaved(true);
|
|
setTimeout(() => setSaved(false), 2000);
|
|
};
|
|
|
|
return (
|
|
<div className="max-w-2xl mx-auto space-y-8 p-4 md:p-8">
|
|
<div>
|
|
<h2 className="text-2xl font-bold mb-2">Settings</h2>
|
|
<p className="text-muted-foreground">Configure your AI image generation provider.</p>
|
|
</div>
|
|
|
|
{/* Provider Selection */}
|
|
<div className="space-y-3">
|
|
<label className="text-sm font-medium">Image Generation Provider</label>
|
|
<div className="grid grid-cols-3 gap-3">
|
|
{providers.map((p) => (
|
|
<button
|
|
key={p.id}
|
|
onClick={() => setProvider(p.id)}
|
|
className={cn(
|
|
"flex flex-col items-center gap-2 p-4 rounded-xl border-2 transition-all",
|
|
provider === p.id
|
|
? "border-primary bg-primary/10"
|
|
: "border-border hover:border-primary/50 bg-card"
|
|
)}
|
|
>
|
|
<p.icon className={cn(
|
|
"h-6 w-6",
|
|
provider === p.id ? "text-primary" : "text-muted-foreground"
|
|
)} />
|
|
<span className={cn(
|
|
"font-medium text-sm",
|
|
provider === p.id ? "text-primary" : ""
|
|
)}>{p.name}</span>
|
|
<span className="text-xs text-muted-foreground">{p.description}</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Provider-specific settings */}
|
|
<div className="space-y-4 p-4 rounded-xl bg-card border">
|
|
{provider === 'whisk' && (
|
|
<div className="space-y-2">
|
|
<label className="text-sm font-medium">Google Whisk Cookies</label>
|
|
<textarea
|
|
value={whiskCookies}
|
|
onChange={(e) => setWhiskCookies(e.target.value)}
|
|
placeholder="Paste your cookies here..."
|
|
className="w-full h-32 p-3 rounded-lg bg-secondary/50 border border-border focus:ring-2 focus:ring-primary/50 outline-none font-mono text-xs"
|
|
/>
|
|
<p className="text-xs text-muted-foreground">
|
|
Get from <a href="https://labs.google/fx/tools/whisk/project" target="_blank" className="underline hover:text-primary">Whisk</a> using <a href="https://cookie-editor.com/" target="_blank" className="underline hover:text-primary">Cookie-Editor</a>.
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
{provider === 'meta' && (
|
|
<div className="space-y-4">
|
|
|
|
{/* Advanced Settings (Hidden by default) */}
|
|
<details className="group mb-4">
|
|
<summary className="flex items-center gap-2 cursor-pointer text-xs text-white/40 hover:text-white/60 mb-2 select-none">
|
|
<Settings2 className="h-3 w-3" />
|
|
<span>Advanced Configuration</span>
|
|
</summary>
|
|
|
|
<div className="pl-4 border-l border-white/5 space-y-4 mb-4">
|
|
<div className="flex items-center justify-between p-3 rounded-lg bg-secondary/30 border border-border/50">
|
|
<div className="space-y-0.5">
|
|
<label className="text-sm font-medium text-white/70">Use Free API Wrapper</label>
|
|
<p className="text-[10px] text-muted-foreground">Running locally via Docker</p>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<span className={`text-xs ${useMetaFreeWrapper ? "text-primary font-medium" : "text-muted-foreground"}`}>{useMetaFreeWrapper ? "ON" : "OFF"}</span>
|
|
<button
|
|
onClick={() => setUseMetaFreeWrapper(!useMetaFreeWrapper)}
|
|
className={`relative inline-flex h-5 w-9 items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 ${useMetaFreeWrapper ? "bg-primary" : "bg-input"}`}
|
|
>
|
|
<span className={`pointer-events-none block h-3.5 w-3.5 rounded-full bg-background shadow-lg ring-0 transition-transform ${useMetaFreeWrapper ? "translate-x-4" : "translate-x-0.5"}`} />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{useMetaFreeWrapper && (
|
|
<div className="space-y-2">
|
|
<label className="text-sm font-medium text-white/70">Free Wrapper URL</label>
|
|
<input
|
|
type="text"
|
|
value={metaFreeWrapperUrl}
|
|
onChange={(e) => setMetaFreeWrapperUrl(e.target.value)}
|
|
placeholder="http://localhost:8000"
|
|
className="w-full p-2 rounded-lg bg-secondary/30 border border-border/50 focus:ring-1 focus:ring-primary/50 outline-none font-mono text-xs text-white/60"
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</details>
|
|
|
|
<div className="pt-2 border-t border-white/5">
|
|
<p className="text-sm font-medium mb-3 text-amber-400">Authentication Required</p>
|
|
|
|
{/* Meta AI Cookies */}
|
|
<div className="space-y-2 mb-4">
|
|
<label className="text-sm font-medium">Meta.ai Cookies</label>
|
|
<textarea
|
|
value={metaCookies}
|
|
onChange={(e) => setMetaCookies(e.target.value)}
|
|
placeholder="Paste cookies from meta.ai..."
|
|
className="w-full h-32 p-3 rounded-lg bg-secondary/50 border border-border focus:ring-2 focus:ring-primary/50 outline-none font-mono text-xs"
|
|
/>
|
|
<p className="text-xs text-muted-foreground">
|
|
Get from logged-in <a href="https://www.meta.ai" target="_blank" className="underline hover:text-primary">meta.ai</a> session.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Facebook Cookies */}
|
|
<div className="space-y-2">
|
|
<label className="text-sm font-medium">Facebook.com Cookies <span className="text-red-500">*</span></label>
|
|
<textarea
|
|
value={facebookCookies}
|
|
onChange={(e) => setFacebookCookies(e.target.value)}
|
|
placeholder="Paste cookies from facebook.com (REQUIRED for authentication)..."
|
|
className="w-full h-32 p-3 rounded-lg bg-secondary/50 border border-border focus:ring-2 focus:ring-primary/50 outline-none font-mono text-xs"
|
|
/>
|
|
<p className="text-xs text-muted-foreground">
|
|
<strong>Required:</strong> Meta AI authenticates via Facebook. Get from logged-in <a href="https://www.facebook.com" target="_blank" className="underline hover:text-primary">facebook.com</a> session using Cookie-Editor.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="pt-4">
|
|
<button
|
|
onClick={handleSave}
|
|
className="flex items-center gap-2 px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 transition-colors"
|
|
>
|
|
<Save className="h-4 w-4" />
|
|
{saved ? "Saved!" : "Save Settings"}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|