112 lines
4.6 KiB
PHP
112 lines
4.6 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Resources\Styles\Pages;
|
|
|
|
use App\Api\Plugins\PluginLoader;
|
|
use App\Filament\Resources\Styles\StyleResource;
|
|
use App\Models\AiModel;
|
|
use App\Models\Image;
|
|
use App\Models\Style;
|
|
use Filament\Actions\Action;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Resources\Pages\CreateRecord;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
|
|
class CreateStyle extends CreateRecord
|
|
{
|
|
protected static string $resource = StyleResource::class;
|
|
|
|
protected function getHeaderActions(): array
|
|
{
|
|
return [
|
|
Action::make('generate_preview')
|
|
->label(__('filament.resource.style.preview.generate'))
|
|
->icon('heroicon-o-sparkles')
|
|
->color('gray')
|
|
->action(function (): void {
|
|
try {
|
|
$state = $this->form->getState();
|
|
$path = $state['preview_source'] ?? null;
|
|
$aiModelId = $state['ai_model_id'] ?? null;
|
|
$prompt = $state['prompt'] ?? null;
|
|
|
|
if (! $path) {
|
|
throw new \RuntimeException(__('filament.resource.style.preview.missing_image'));
|
|
}
|
|
if (! $aiModelId) {
|
|
throw new \RuntimeException(__('filament.resource.style.preview.missing_model'));
|
|
}
|
|
if (! $prompt) {
|
|
throw new \RuntimeException(__('filament.resource.style.preview.missing_prompt'));
|
|
}
|
|
|
|
$aiModel = AiModel::with('primaryApiProvider')->findOrFail($aiModelId);
|
|
$provider = $aiModel->primaryApiProvider;
|
|
if (! $provider || ! $provider->enabled || ! $provider->plugin || ! $provider->token) {
|
|
throw new \RuntimeException(__('filament.resource.style.preview.provider_invalid'));
|
|
}
|
|
|
|
$style = new Style([
|
|
'title' => $state['title'] ?? 'Preview',
|
|
'prompt' => $prompt,
|
|
'description' => $state['description'] ?? '',
|
|
'parameters' => $state['parameters'] ?? [],
|
|
]);
|
|
$style->setRelation('aiModel', $aiModel);
|
|
|
|
$image = new Image([
|
|
'path' => $path,
|
|
]);
|
|
|
|
$plugin = PluginLoader::getPlugin($provider->plugin, $provider);
|
|
$result = $plugin->processImageStyleChange($image, $style);
|
|
|
|
$imageData = null;
|
|
if (isset($result['base64Data'])) {
|
|
$imageData = base64_decode($result['base64Data']);
|
|
} elseif (isset($result['prompt_id'])) {
|
|
$fetched = $plugin->getStyledImage($result['prompt_id']);
|
|
if (str_starts_with($fetched, 'http')) {
|
|
$resp = Http::timeout(30)->get($fetched);
|
|
$resp->throw();
|
|
$imageData = $resp->body();
|
|
} else {
|
|
$imageData = base64_decode($fetched);
|
|
}
|
|
}
|
|
|
|
if (! $imageData) {
|
|
throw new \RuntimeException(__('filament.resource.style.preview.no_image'));
|
|
}
|
|
|
|
$fileName = 'style_previews/generated_'.Str::uuid().'.png';
|
|
Storage::disk('public')->put($fileName, $imageData);
|
|
|
|
$this->form->fill([
|
|
'preview_image' => $fileName,
|
|
]);
|
|
|
|
Notification::make()
|
|
->title(__('filament.resource.style.preview.done'))
|
|
->body(__('filament.resource.style.preview.saved_hint'))
|
|
->success()
|
|
->send();
|
|
} catch (\Throwable $e) {
|
|
Notification::make()
|
|
->title(__('filament.resource.style.preview.failed'))
|
|
->body($e->getMessage())
|
|
->danger()
|
|
->send();
|
|
}
|
|
}),
|
|
];
|
|
}
|
|
|
|
protected function getRedirectUrl(): string
|
|
{
|
|
return $this->getResource()::getUrl('index');
|
|
}
|
|
}
|