Use frontend-selected characters instead of fetching recent ones

This commit is contained in:
Riccardo Giorato
2025-12-26 21:57:25 +01:00
parent ddf05e6259
commit a618754337
6 changed files with 278 additions and 93 deletions
+2 -6
View File
@@ -10,7 +10,6 @@ import {
getNextPageNumber,
getStoryWithPagesBySlug,
getLastPageImage,
getStoryCharacterImages,
} from "@/lib/db-actions";
import { freeTierRateLimit } from "@/lib/rate-limit";
import { uploadImageToS3 } from "@/lib/s3-upload";
@@ -134,11 +133,8 @@ export async function POST(request: NextRequest) {
}
}
// Get story character images (up to 2 most recent)
const storyCharacterImages = await getStoryCharacterImages(story.id);
referenceImages.push(...storyCharacterImages.slice(-2)); // Take last 2
// Add current character images to references
// Use only the character images sent from the frontend (user's selection)
// These are already the most recent/relevant characters the user wants to use
referenceImages.push(...characterImages);
// Build the prompt with continuation context
+3 -4
View File
@@ -119,9 +119,8 @@ export async function POST(request: NextRequest) {
}
}
// Get story character images (up to 2 most recent)
const storyCharacterImages = await getStoryCharacterImages(storyId);
referenceImages.push(...storyCharacterImages.slice(-2)); // Take last 2
// For continuation pages, character images are sent from frontend
// No need to fetch separately - frontend handles selection
} else {
// New story: no previous page reference
// Create story with temporary title, will update with generated title
@@ -140,7 +139,7 @@ export async function POST(request: NextRequest) {
});
}
// Add current character images to references
// Use only the character images sent from the frontend
referenceImages.push(...characterImages);
const dimensions = FIXED_DIMENSIONS;
+2
View File
@@ -21,6 +21,7 @@ export async function GET() {
id: stories.id,
title: stories.title,
slug: stories.slug,
style: stories.style,
createdAt: stories.createdAt,
pageCount: pages.pageNumber,
coverImage: pages.generatedImageUrl,
@@ -41,6 +42,7 @@ export async function GET() {
id: row.id,
title: row.title,
slug: row.slug,
style: row.style,
createdAt: row.createdAt,
pageCount: 0,
coverImage: null,
+23 -3
View File
@@ -319,6 +319,15 @@ export function StoryEditorClient() {
const result = await response.json();
// Update character images list with new ones
const newCharacterUrls = data.characterUrls || [];
setExistingCharacterImages((prev) => {
const combined = [...prev, ...newCharacterUrls];
// Remove duplicates while preserving order
const unique = Array.from(new Set(combined));
return unique;
});
setPages((prevPages) => [
...prevPages,
{
@@ -400,6 +409,17 @@ export function StoryEditorClient() {
onClose={() => setShowGenerateModal(false)}
onGenerate={handleGeneratePage}
pageNumber={pages.length + 1}
existingCharacters={existingCharacterImages}
lastPageCharacters={
pages.length > 0 && pages[pages.length - 1]?.characterUploads
? pages[pages.length - 1].characterUploads || []
: []
}
previousPageCharacters={
pages.length > 1 && pages[pages.length - 2]?.characterUploads
? pages[pages.length - 2].characterUploads || []
: []
}
/>
<PageInfoSheet
isOpen={showInfoSheet}
@@ -412,8 +432,9 @@ export function StoryEditorClient() {
<AlertDialogHeader>
<AlertDialogTitle>Delete Page</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete page {pageToDelete !== null ? pageToDelete + 1 : ""}?
This action cannot be undone.
Are you sure you want to delete page{" "}
{pageToDelete !== null ? pageToDelete + 1 : ""}? This action
cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
@@ -430,4 +451,3 @@ export function StoryEditorClient() {
</div>
);
}
+9 -7
View File
@@ -6,11 +6,13 @@ import { Button } from "@/components/ui/button";
import { Plus, Loader2 } from "lucide-react";
import { Navbar } from "@/components/landing/navbar";
import { StoryLoader } from "@/components/ui/story-loader";
import { COMIC_STYLES } from "@/lib/constants";
interface Story {
id: string;
title: string;
slug: string;
style: string;
createdAt: string;
pageCount: number;
coverImage: string | null;
@@ -131,7 +133,7 @@ export default function StoriesPage() {
<button
key={story.id}
onClick={() => router.push(`/editor/${story.slug}`)}
className={`opacity-0 animate-fade-in-up group relative glass-panel p-3 rounded-lg hover:shadow-indigo/20 hover:shadow-2xl transition-all duration-500 hover:scale-[1.05] hover:-translate-y-2 border border-border/50 hover:border-indigo/30 hover:bg-white/[0.02] backdrop-blur-sm`}
className={`opacity-0 animate-fade-in-up group relative glass-panel p-3 rounded-lg hover:shadow-indigo/20 hover:shadow-2xl transition-all duration-500 hover:scale-[1.05] hover:-translate-y-2 border border-border/50 hover:border-indigo/30 hover:bg-white/[0.02] backdrop-blur-sm focus:outline-none`}
style={{ animationDelay: `${200 + index * 100}ms` }}
>
<div className="w-full h-full bg-neutral-900 border-4 border-black overflow-hidden relative group-hover:border-indigo/30 transition-colors duration-300">
@@ -157,14 +159,14 @@ export default function StoriesPage() {
{/* Subtle glow effect on hover */}
<div className="absolute inset-0 opacity-0 group-hover:opacity-20 bg-gradient-to-r from-indigo/20 via-transparent to-emerald/20 transition-opacity duration-500" />
<div className="absolute top-2 right-2 px-1.5 py-0.5 bg-black/80 text-white text-[9px] font-mono uppercase tracking-widest border border-white/20 group-hover:bg-indigo/80 group-hover:border-indigo/40 transition-colors duration-300">
{story.pageCount}p
</div>
<div className="absolute top-2 right-2 px-1.5 py-0.5 bg-black/80 text-white text-[9px] font-mono uppercase tracking-widest border border-white/20 group-hover:bg-indigo/80 group-hover:border-indigo/40 transition-colors duration-300">
{COMIC_STYLES.find(s => s.id === story.style)?.name.toUpperCase() || story.style.toUpperCase()}
</div>
<div className="absolute bottom-0 left-0 right-0 p-3 text-left">
<h3 className="font-display text-sm text-white leading-tight line-clamp-2 mb-1 group-hover:text-indigo-100 transition-colors duration-300">
{story.title}
</h3>
<h3 className="font-display text-sm text-white leading-tight line-clamp-1 mb-1 group-hover:text-indigo-100 transition-colors duration-300">
{story.title}
</h3>
<p className="text-[10px] text-white/60 font-mono uppercase tracking-wider group-hover:text-white/80 transition-colors duration-300">
{new Date(story.createdAt).toLocaleDateString()}
</p>