From bb55e1442371018108daa5d5b1317934b735d69f Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Wed, 17 Jun 2026 18:09:02 -0300 Subject: [PATCH] fix(ai-templates): paragraph spacing bug, registry cache, coverage gaps, empty-account UX --- app/Ai/Templates/AiTemplateRegistry.php | 5 ++- app/Http/Controllers/App/PostController.php | 3 +- app/Services/Image/TemplateImageGenerator.php | 2 +- lang/en/posts.php | 1 + lang/es/posts.php | 1 + lang/pt-BR/posts.php | 1 + .../components/posts/create/AiPostWizard.vue | 5 ++- tests/Feature/Ai/StreamPostCreationTest.php | 2 + .../Ai/Templates/AiTemplateRegistryTest.php | 2 +- .../Ai/Templates/TweetCardRenderTest.php | 43 +++++++++++++++++++ 10 files changed, 60 insertions(+), 5 deletions(-) diff --git a/app/Ai/Templates/AiTemplateRegistry.php b/app/Ai/Templates/AiTemplateRegistry.php index f1be810a..c81716e0 100644 --- a/app/Ai/Templates/AiTemplateRegistry.php +++ b/app/Ai/Templates/AiTemplateRegistry.php @@ -15,10 +15,13 @@ class AiTemplateRegistry TweetCardTemplate::class, ]; + /** @var array|null */ + private ?array $templates = null; + /** @return array */ public function all(): array { - return array_map(fn (string $class) => app($class), self::TEMPLATES); + return $this->templates ??= array_map(fn (string $class) => app($class), self::TEMPLATES); } /** @return array */ diff --git a/app/Http/Controllers/App/PostController.php b/app/Http/Controllers/App/PostController.php index 5c7f9c7f..65576b9c 100644 --- a/app/Http/Controllers/App/PostController.php +++ b/app/Http/Controllers/App/PostController.php @@ -9,6 +9,7 @@ use App\Actions\Post\DuplicatePost; use App\Actions\Post\SyncPostPlatforms; use App\Actions\Post\UpdatePost; +use App\Ai\Templates\AiContentTemplate; use App\Ai\Templates\AiTemplateRegistry; use App\Enums\Post\Action as PostAction; use App\Enums\Post\Status as PostStatus; @@ -145,7 +146,7 @@ public function create(Request $request): Response $registry = app(AiTemplateRegistry::class); - $templates = array_map(fn ($t) => [ + $templates = array_map(fn (AiContentTemplate $t) => [ 'key' => $t->key(), 'name' => trans($t->name()), 'description' => trans($t->description()), diff --git a/app/Services/Image/TemplateImageGenerator.php b/app/Services/Image/TemplateImageGenerator.php index dbd76322..a4be6670 100644 --- a/app/Services/Image/TemplateImageGenerator.php +++ b/app/Services/Image/TemplateImageGenerator.php @@ -590,7 +590,7 @@ public function renderTweetCard(Workspace $workspace, SocialAccount $socialAccou $bodyLineHeight = 1.55; $paragraphGap = (int) round($bodySize * $bodyLineHeight * 0.6); - $paragraphs = array_filter(array_map('trim', explode("\n\n", $tweetText)), fn ($p) => $p !== ''); + $paragraphs = array_values(array_filter(array_map('trim', explode("\n\n", $tweetText)), fn ($p) => $p !== '')); $allBodyLines = []; foreach ($paragraphs as $i => $para) { $lines = ($fontMedium ? $this->wrapText($para, $fontMedium, $bodySize, $cardW - 2 * $cardPadding) : [str_replace("\n", ' ', $para)]); diff --git a/lang/en/posts.php b/lang/en/posts.php index b966ee45..252754f5 100644 --- a/lang/en/posts.php +++ b/lang/en/posts.php @@ -620,6 +620,7 @@ 'retry' => 'Try again', 'no_platforms' => 'No connected accounts', 'connect_first' => 'Connect at least one social account to use AI generation.', + 'no_account_for_template' => 'Connect a compatible account to use this template.', 'format' => [ 'instagram_feed' => 'Instagram Feed Post', diff --git a/lang/es/posts.php b/lang/es/posts.php index 6926f152..4dd580e6 100644 --- a/lang/es/posts.php +++ b/lang/es/posts.php @@ -621,6 +621,7 @@ 'retry' => 'Intentar de nuevo', 'no_platforms' => 'Sin cuentas conectadas', 'connect_first' => 'Conecta al menos una cuenta social para usar la generación con IA.', + 'no_account_for_template' => 'Conecta una cuenta compatible para usar esta plantilla.', 'format' => [ 'instagram_feed' => 'Post de Feed de Instagram', diff --git a/lang/pt-BR/posts.php b/lang/pt-BR/posts.php index c19e0b2a..c9fdc07c 100644 --- a/lang/pt-BR/posts.php +++ b/lang/pt-BR/posts.php @@ -620,6 +620,7 @@ 'retry' => 'Tentar novamente', 'no_platforms' => 'Nenhuma conta conectada', 'connect_first' => 'Conecte pelo menos uma conta social para usar a geração com IA.', + 'no_account_for_template' => 'Conecte uma conta compatível para usar este template.', 'format' => [ 'instagram_feed' => 'Post no Feed do Instagram', diff --git a/resources/js/components/posts/create/AiPostWizard.vue b/resources/js/components/posts/create/AiPostWizard.vue index 566e0229..d4592bf2 100644 --- a/resources/js/components/posts/create/AiPostWizard.vue +++ b/resources/js/components/posts/create/AiPostWizard.vue @@ -337,7 +337,10 @@ const startGeneration = async () => {
-
+

+ {{ $t('posts.create.steps.no_account_for_template') }} +

+