fix: slide 3 noire, watermark PPTX, quota génération slides
- canvas-board.tsx: préfère data.html (iframe) sur data.spec (ancien renderer) → corrige slide 3 noire en mode HTML viewer - pptx/route.ts: ajoute watermark 'memento-note.com' sur chaque slide via buildPptx (PPTX téléchargé depuis le canvas) - run-for-note/route.ts: checkEntitlementOrThrow avant création agent - slides.tool.ts: incrementUsageAsync après canvas créé avec succès Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { auth } from '@/auth'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
import { checkEntitlementOrThrow, QuotaExceededError, incrementUsageAsync } from '@/lib/entitlements'
|
||||
|
||||
type GenerateType = 'slide-generator' | 'excalidraw-generator'
|
||||
|
||||
@@ -43,6 +44,16 @@ export async function POST(req: NextRequest) {
|
||||
return NextResponse.json({ error: 'Paramètres invalides' }, { status: 400 })
|
||||
}
|
||||
|
||||
// Quota check — slides/excalidraw generation counts as 'reformulate' credit
|
||||
try {
|
||||
await checkEntitlementOrThrow(userId, 'reformulate')
|
||||
} catch (e) {
|
||||
if (e instanceof QuotaExceededError) {
|
||||
return NextResponse.json({ error: e.message }, { status: 402 })
|
||||
}
|
||||
throw e
|
||||
}
|
||||
|
||||
const note = await prisma.note.findFirst({
|
||||
where: { id: noteId, userId },
|
||||
select: { id: true, title: true, notebookId: true },
|
||||
|
||||
@@ -43,6 +43,12 @@ async function buildPptx(spec: any): Promise<Buffer> {
|
||||
|
||||
for (const slide of (spec.slides ?? [])) {
|
||||
const s = pptx.addSlide()
|
||||
// PLG watermark — bottom-right corner of LAYOUT_WIDE (13.33"×7.5")
|
||||
s.addText('memento-note.com', {
|
||||
x: 10.0, y: 7.1, w: 3.0, h: 0.25,
|
||||
fontSize: 7, fontFace: 'Arial', color: 'B8B0A8',
|
||||
align: 'right', italic: true,
|
||||
})
|
||||
|
||||
switch (slide.type) {
|
||||
case 'title': {
|
||||
|
||||
@@ -218,11 +218,10 @@ function SlidesViewer({ data, name, canvasId }: { data: SlidesPayload; name: str
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/* Slides: React renderer (legacy spec) or iframe (new HTML) */}
|
||||
{/* Slides: iframe (new HTML format) preferred over legacy React renderer */}
|
||||
<div className="flex-1 relative overflow-hidden group">
|
||||
{data.spec ? (
|
||||
<SlidesRenderer spec={data.spec} />
|
||||
) : (
|
||||
{data.html ? (
|
||||
// New format: standalone animated HTML served via srcDoc
|
||||
<>
|
||||
{/* Loading overlay — visible until iframe fires onLoad */}
|
||||
{!isLoaded && (
|
||||
@@ -257,7 +256,10 @@ function SlidesViewer({ data, name, canvasId }: { data: SlidesPayload; name: str
|
||||
<ChevronRight className="w-5 h-5" />
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
) : data.spec ? (
|
||||
// Legacy format: old React renderer (recharts)
|
||||
<SlidesRenderer spec={data.spec} />
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -5,6 +5,7 @@ import { z } from 'zod'
|
||||
import { toolRegistry } from './registry'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
import { buildPresentationHTML } from './slides-html-builder'
|
||||
import { incrementUsageAsync } from '@/lib/entitlements'
|
||||
|
||||
const slideSchema = z.discriminatedUnion('type', [
|
||||
z.object({ type: z.literal('title'), title: z.string(), subtitle: z.string().optional() }),
|
||||
@@ -80,6 +81,9 @@ RULES:
|
||||
|
||||
console.log('[Slides Tool] Canvas created:', canvas.id, '| Slides:', slides.length, '| Size:', Math.round(html.length / 1024), 'KB')
|
||||
|
||||
// Decrement reformulate quota (agent-based generation consumes credits)
|
||||
incrementUsageAsync(ctx.userId, 'reformulate')
|
||||
|
||||
if (ctx.actionId) {
|
||||
await prisma.agentAction.update({
|
||||
where: { id: ctx.actionId },
|
||||
|
||||
Reference in New Issue
Block a user