Use frontend-selected characters instead of fetching recent ones
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user