import { Observable } from 'rxjs'; import { CreateFeedbackResponse, GetFeedbackResponse, CheckFeedbackResponse, DeviceContext, FeedbackType, ContentRef, EntityRef, ReactionValue } from './types'; import * as i0 from "@angular/core"; /** * Servicio para gestionar feedback de usuarios. * * @example * ```typescript * @Component({...}) * export class MyComponent { * private feedbackService = inject(FeedbackService); * * async submitFeedback() { * const response = await this.feedbackService.createAsync( * 'feedback', * 'Mi comentario', * 'Descripción detallada...' * ); * console.log('Feedback enviado:', response.feedbackId); * } * } * ``` */ export declare class FeedbackService { private config; private http; private firestore; private storage; private auth; readonly isConfigured: import("@angular/core").WritableSignal; constructor(); /** * URL base para endpoints de feedback. */ private get baseUrl(); /** * Captura el contexto del dispositivo automáticamente. */ captureDeviceContext(): DeviceContext; /** * Crea un nuevo feedback. * * @param type - Tipo de feedback * @param title - Título del feedback * @param description - Descripción detallada * @param attachments - URLs de archivos adjuntos (opcional) * @param contentRef - Referencia a contenido específico (opcional) * @returns Observable con la respuesta */ create(type: FeedbackType, title: string, description: string, attachments?: string[], contentRef?: ContentRef): Observable; /** * Crea un nuevo feedback (versión async/await). */ createAsync(type: FeedbackType, title: string, description: string, attachments?: string[], contentRef?: ContentRef): Promise; /** * Obtiene un feedback por ID (solo el propietario). * * @param feedbackId - ID del feedback * @returns Observable con la respuesta */ getById(feedbackId: string): Observable; /** * Obtiene un feedback por ID (versión async/await). */ getByIdAsync(feedbackId: string): Promise; /** * Valida si un archivo cumple con las restricciones. */ validateFile(file: File): { valid: boolean; error?: string; }; /** * Valida el CONTENIDO del archivo por magic-bytes (firma binaria) — * defensa contra spoofing del content-type declarado. Lee los primeros 12 * bytes y los compara con las firmas de JPEG/PNG/WebP/PDF (whitelist * estricta). Es client-side, ergo bypasseable; la defensa real vive en las * Storage rules. Esto corta el 99% de los casos accidentales o no-targeted. */ validateFileContent(file: File): Promise<{ valid: boolean; error?: string; }>; /** * Sube un adjunto a Firebase Storage en `users/{uid}/feedback/{uuid}/{name}` * y devuelve su download URL. Ejecuta tres validaciones en orden: * 1. tamaño + tipo declarado (`validateFile`) * 2. contenido por magic-bytes (`validateFileContent`) * 3. usuario autenticado (no soportamos adjuntos en feedback anónimo) * * Si cualquier validación falla → rechaza la promesa con un Error legible; * el componente que la consuma debe cancelar la operación de adjuntar. */ uploadAttachment(file: File): Promise; /** * Obtiene la configuración actual del servicio. */ getConfig(): Readonly; /** * Verifica si el usuario ya dio feedback para una entidad específica. * * Primero intenta leer de Firebase (rápido, sin latencia de red al backend). * Si Firebase no está disponible o falla, hace fallback a la API. * * @param entityType - Tipo de entidad (article, docs, feature, etc.) * @param entityId - ID de la entidad * @returns Promise con la respuesta de verificación * * @example * ```typescript * const check = await this.feedbackService.checkFeedback('article', 'art-123'); * if (check.hasFeedback) { * console.log('Ya dio feedback:', check.reactionValue); * } * ``` */ checkFeedback(entityType: string, entityId: string): Promise; /** * Crea o actualiza una reacción (feedback con emoji). * * @param entityRef - Referencia a la entidad * @param value - Valor de la reacción (negative, neutral, positive) * @param comment - Comentario opcional (máx 500 caracteres) * @returns Promise con la respuesta * * @example * ```typescript * const response = await this.feedbackService.createReaction( * { entityType: 'article', entityId: 'art-123' }, * 'positive', * 'Muy útil!' * ); * ``` */ createReaction(entityRef: EntityRef, value: ReactionValue, comment?: string): Promise; /** * Crea feedback anónimo (sin autenticación requerida). * Usado para blogs, FAQs y contenido público. * * @param entityRef - Referencia a la entidad * @param value - Valor de la reacción (negative, neutral, positive) * @param comment - Comentario opcional (máx 500 caracteres) * @returns Promise con la respuesta * * @example * ```typescript * // En un blog público * const response = await this.feedbackService.createAnonymousReaction( * { entityType: 'blog', entityId: 'my-post-slug' }, * 'positive' * ); * ``` */ createAnonymousReaction(entityRef: EntityRef, value: ReactionValue, comment?: string): Promise; private detectBrowser; private detectOS; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; }