import type { JsonWebKey } from 'crypto'; import type { IAgoraRTCClient, ICameraVideoTrack, IMicrophoneAudioTrack, IAgoraRTCRemoteUser } from 'agora-rtc-sdk-ng'; import { z } from 'zod'; export type Language = 'en' | 'ar'; export type VideoQuality = 'low' | 'medium' | 'high'; export type AppTheme = 'light' | 'dark' | 'theme-neon-nights' | 'theme-desert-oasis' | 'theme-kyoto-garden'; export interface UserProfile { uid: string; displayName: string; photoURL: string; publicId: string; bio?: string; status?: string; publicKey?: JsonWebKey; blockedUsers?: { [uid: string]: true }; blockedBy?: { [uid: string]: true }; fcmToken?: string; privacySettings?: PrivacySettings; } export interface User extends UserProfile { isOnline?: boolean; lastSeen?: number | object; } export interface ChatRecipient extends User { isGroup?: boolean; isBot?: boolean; } export interface Contact { uid: string; name: string; addedAt: number; photoURL?: string; publicId: string; publicKey?: JsonWebKey; isOnline?: boolean; } export type GroupType = 'general' | 'study' | 'friends' | 'gaming'; export type GroupSendingMode = 'everyone' | 'admins' | 'owner'; export interface Group { id: string; info: { name: string; photoURL: string; createdBy: string; createdAt: number; description?: string; type: GroupType; settings?: { sendingMode?: GroupSendingMode; }; mutedMembers?: { [uid: string]: true }; }; members: { [uid: string]: true }; admins: { [uid: string]: true }; encryptedKeys: { [uid: string]: string }; keyLastRotatedAt?: number; } export interface GroupMember extends User { isAdmin: boolean; isMuted?: boolean; } export interface GroupInvitation { groupId: string; groupName: string; groupPhotoURL: string; invitedBy: string; } export interface ChatRequest { fromUid: string; displayName: string; photoURL: string; publicId: string; timestamp: number; } export interface ReplyTo { id: string; text: string; displayName: string; imageKey?: string; videoKey?: string; audioKey?: string; } export interface URLPreviewData { url: string; title: string; description?: string; imageUrl?: string; domain: string; } export interface EncryptedMessage { iv: number[]; ciphertext: number[]; } export interface ActionPayload { type: string; } export interface Message { id: string; text?: string | null; encryptedText?: string | null; compressedText?: string; // For ultra saving mode originalSize?: number; // Size before compression compressedSize?: number; // Size after compression timestamp: number; editedAt?: number; reactions?: { [key: string]: { [uid: string]: { displayName: string } } }; audioKey?: string; audioDuration?: number; transcription?: string; imageKey?: string; videoKey?: string; fileKey?: string; fileName?: string; fileSize?: number; fileType?: string; encryptionKey?: { [uid: string]: string } | { group: string }; // Key to decrypt media files, per user OR for group keyVersion?: number; // Timestamp of the group key used for this message urlPreviewData?: URLPreviewData; isDeleted?: boolean; isSystemMessage?: boolean; status?: 'sent' | 'pending' | 'failed'; uploadProgress?: number; // For optimistic UI on uploads replyTo?: ReplyTo | null; sender: string; senderDisplayName: string; senderPhotoUrl: string; isSender?: boolean; deliveredTo?: { [uid: string]: number }; readBy?: { [uid:string]: number }; detectedLang?: string; action?: ActionPayload; } export interface ChatInfo { type: 'private' | 'group' | 'public'; participants: { [uid: string]: true | { lastRead: number } }; status?: 'accepted' | 'blocked'; initiator?: string; } export interface Reaction { emoji: string; users: string[]; } export type DataMode = 'normal' | 'ultra'; export type FontStyle = 'default' | 'casual'; export interface AIUser { id:string; name: string; avatarUrl: string; } export enum PostCategory { Funny = 'funny', Sad = 'sad', Deep = 'deep', Angry = 'angry', Inspirational = 'inspirational', General = 'general' } export interface LiveReaction { id: string; emoji: string; } export interface AIComment { id: string; author: AIUser; text: string; reactions: { [key: string]: number }; uiState: { userReaction: string | null; liveReactions: LiveReaction[]; }; } export interface AIPost { id: string; author: AIUser; content: string; imageUrl: string; imageQuery: string; isMeme: boolean; reactions: { [key: string]: number }; comments: AIComment[]; createdAt: string; category: PostCategory; } export type PostWithUIState = AIPost & { uiState: { userReaction: string | null; // e.g., 'heart', 'laugh', null showCommentInput: boolean; isGeneratingComment: boolean; hasGeneratedBulkComments: boolean; liveReactions: LiveReaction[]; }; }; // For Group Chat export interface Persona { name: string; avatarUrl: string; } export interface GroupChatMessage { personaName: string; message: string; } export interface PrivacySettings { showOnline: boolean; showTyping: boolean; readReceipts: boolean; whoCanAdd: 'everyone' | 'contacts'; whoCanViewProfile: 'everyone' | 'contacts'; } // --- WebRTC Call Types --- export type CallType = 'audio' | 'video'; export interface CallState { status: 'idle' | 'outgoing' | 'incoming' | 'connected' | 'connecting'; peer: UserProfile | null; type: CallType | null; channelName: string | null; isMuted: boolean; isVideoOff: boolean; startTime: number | null; } export interface CallSignal { offer?: boolean; answer?: boolean; caller?: UserProfile; type?: CallType; channelName?: string; iceCandidate?: any; connected?: boolean; ended?: boolean; rejected?: boolean; } export interface PresenceStatus { isOnline: boolean; lastSeen: number; isBusy?: boolean; } // AI Schemas for Genkit export const GenerateImageInputSchema = z.object({ prompt: z.string().describe('A descriptive prompt for the image generation model.'), }); export type GenerateImageInput = z.infer; export const GenerateImageOutputSchema = z.object({ imageUrl: z.string().describe('The data URI of the generated image.'), }); export type GenerateImageOutput = z.infer; export interface LocalAiAction { type: string; keywords: { en: string[]; ar: string[]; }; response: { en: string; ar: string; }; } export const MessageSchema = z.object({ role: z.enum(['user', 'model']), content: z.array(z.object({ text: z.string() })), }); export type Message = z.infer;