/* * AI 생성 이미지 — 워터마크 상시 오버레이 + "AI 생성 예상 이미지" 고지문(제거 불가). * 계약: 01_backend_contracts.md §0-3 (watermarkRequired/watermarkText/notice 항상 포함). * design.md §1-4: 생성 이미지는 카드 하단 고지문 항상 노출. */ import React from 'react'; import { Image, StyleSheet, Text, View, type StyleProp, type ViewStyle } from 'react-native'; import { AI_IMAGE_NOTICE } from '../lib/config'; import { colors, radius, type } from '../theme'; interface Props { uri: string | null; /** 상태: 생성 중/실패 표시. */ status?: 'DONE' | 'QUEUED' | 'RUNNING' | 'FAILED'; watermarkText?: string; notice?: string; shotBadge?: string; // 예: "S2 야간" height?: number; style?: StyleProp; } export function AiImage({ uri, status = 'DONE', watermarkText, notice, shotBadge, height = 200, style, }: Props) { const wm = watermarkText ?? AI_IMAGE_NOTICE; const loading = status === 'QUEUED' || status === 'RUNNING'; const failed = status === 'FAILED'; return ( {uri && status === 'DONE' ? ( ) : ( {loading ? '생성 중… 평균 40초' : failed ? '생성 실패 — 다시 생성' : '이미지 없음'} )} {/* 워터마크 (상시, 제거 불가) */} {wm} {/* AI 라벨 칩 */} AI 생성 {shotBadge ? ( {shotBadge} ) : null} {/* 하단 고지문 (제거 불가) */} {notice ?? wm} ); } const styles = StyleSheet.create({ wrap: { gap: 6 }, frame: { width: '100%', borderRadius: radius.md, overflow: 'hidden', backgroundColor: colors.neutral050, borderWidth: 1, borderColor: colors.neutral200, }, img: { width: '100%', height: '100%' }, placeholder: { alignItems: 'center', justifyContent: 'center', backgroundColor: colors.aiSurface, }, placeholderText: { color: colors.neutral500, fontSize: type.body.fontSize }, watermarkLayer: { ...StyleSheet.absoluteFillObject, alignItems: 'center', justifyContent: 'center', }, watermark: { color: 'rgba(16,24,40,0.28)', fontSize: 13, fontWeight: '700', transform: [{ rotate: '-18deg' }], textAlign: 'center', paddingHorizontal: 12, }, aiChip: { position: 'absolute', top: 8, left: 8, backgroundColor: colors.aiAccent, borderRadius: radius.pill, paddingHorizontal: 8, paddingVertical: 2, }, aiChipText: { color: colors.white, fontSize: 11, fontWeight: '700' }, shotBadge: { position: 'absolute', top: 8, right: 8, backgroundColor: 'rgba(28,37,54,0.8)', borderRadius: radius.sm, paddingHorizontal: 8, paddingVertical: 2, }, shotBadgeText: { color: colors.white, fontSize: 11, fontWeight: '600' }, notice: { color: colors.neutral500, fontSize: type.caption.fontSize }, });