diff --git a/README.md b/README.md index eb6c22b..962dacc 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,120 @@ # rn-firebase-chat -RN Firebase Chat +A comprehensive React Native chat library built with Firebase, featuring real-time messaging, media sharing, encryption, and customizable UI components. + +## ✨ Features + +### đŸ”Ĩ **Core Chat Functionality** +- **Real-time Messaging** - Instant messaging with Firebase Firestore +- **Message Status Tracking** - Sent, received, seen, and failed status indicators +- **Typing Indicators** - Real-time typing status with customizable timeouts +- **Message Pagination** - Efficient loading of message history with configurable page sizes +- **Conversation Management** - Automatic conversation creation and management + +### 📱 **Media & Content Sharing** +- **Camera Integration** - Built-in camera with photo and video capture + - Front/back camera switching + - Flash control + - Video recording with timer + - Custom camera icons and styling +- **Gallery Support** - Media gallery with three categories: + - **Media Tab** - Images and videos with thumbnail previews + - **Files Tab** - Document sharing (customizable) + - **Links Tab** - Shared links (customizable) +- **Video Player** - Full-featured video player with: + - Play/pause controls + - Seek functionality + - Custom slider support + - Duration display +- **Image Viewer** - Full-screen image viewing with zoom capabilities + +### 🔒 **Security & Privacy** +- **Message Encryption** - Optional AES encryption for secure conversations +- **Custom Encryption Functions** - Support for custom encryption implementations +- **Content Filtering** - Blacklist words with regex pattern support +- **Environment Separation** - Prefix support for dev/staging/production environments + +### 🎨 **Customization & Theming** +- **Highly Customizable UI** - Every component can be styled +- **Custom Message Bubbles** - Support for custom message bubble designs +- **Input Toolbar Customization** - Fully customizable input area with: + - Custom icons and buttons + - Left and right custom views + - Configurable camera and gallery buttons +- **Theme Support** - Built for theme providers and dark mode +- **Responsive Design** - Adaptive layouts for tablets and different screen sizes + +### 🛠 **Developer Experience** +- **TypeScript Support** - Full TypeScript definitions and interfaces +- **React Hooks** - Custom hooks for chat state management and typing indicators +- **Flexible Architecture** - Modular components that can be used independently +- **Extensive Props** - Comprehensive prop interfaces for maximum flexibility +- **Custom Renderers** - Support for custom item renderers in lists and galleries + +### 🔧 **Advanced Features** +- **Performance Optimization** - Efficient message loading and memory management +- **Error Handling** - Built-in error handling for network and encryption failures +- **Firebase Storage Integration** - Automatic media file uploads to Firebase Storage +- **User Profile Management** - Automatic user profile creation and management +- **Real-time Updates** - Live conversation and message updates +- **Search Functionality** - Built-in conversation search capabilities + +## đŸ“Ļ Installation + +### Prerequisites + +Before installing `rn-firebase-chat`, ensure you have the following dependencies in your React Native project: + +#### Core Dependencies +```sh +# Using npm +npm install @react-native-firebase/app @react-native-firebase/firestore @react-native-firebase/storage randomcolor react-native-aes-crypto react-native-gifted-chat react-native-fast-image react-native-video uuid -## Installation +# Using Yarn +yarn add @react-native-firebase/app @react-native-firebase/firestore @react-native-firebase/storage randomcolor react-native-aes-crypto react-native-gifted-chat react-native-fast-image react-native-video uuid +``` +#### Camera Dependencies (Optional - for camera features) ```sh -npm install rn-firebase-chat +# Using npm +npm install react-native-vision-camera + +# Using Yarn +yarn add react-native-vision-camera ``` -## Installation +> **📋 Note:** Camera functionality requires `react-native-vision-camera`. If you don't need camera features, you can skip this dependency and set `hasCamera={false}` in your ChatScreen props. -- Using [npm](https://www.npmjs.com/#getting-started): +### Install the Library ```sh -npm install rn-firebase-chat @react-native-firebase/app @react-native-firebase/firestore @react-native-firebase/storage randomcolor react-native-aes-crypto react-native-gifted-chat --save +# Using npm +npm install rn-firebase-chat + +# Using Yarn +yarn add rn-firebase-chat ``` -- Using [Yarn](https://yarnpkg.com/): +## 🚀 Quick Start -```sh -yarn add rn-firebase-chat @react-native-firebase/app @react-native-firebase/firestore @react-native-firebase/storage randomcolor react-native-aes-crypto react-native-gifted-chat -``` +### 1. Setup Firebase Configuration + +Make sure you have Firebase configured in your React Native project. Add your `google-services.json` (Android) and `GoogleService-Info.plist` (iOS) files to your project. +> **â„šī¸ Note:** For detailed Firebase setup instructions, refer to the [official React Native Firebase documentation](https://rnfirebase.io/#installation-for-react-native-cli-non-expo-projects). -## Usage -- Wrap your app with `ChatProvider` +### 2. Wrap Your App with ChatProvider ```javascript +import React from 'react'; import { ChatProvider } from 'rn-firebase-chat'; +// Note: The `userInfo` object should represent the currently logged-in user in your app. +// Make sure to set these values after user authentication (e.g., after login). const userInfo = { - id: 'abc123', - name: 'John Doe', - avatar: 'https://example.com/avatar.jpg', + id: 'user123', // The unique ID of the logged-in user + name: 'John Doe', // The display name of the logged-in user + avatar: 'https://example.com/avatar.jpg' // The avatar URL of the logged-in user }; function App() { @@ -42,108 +124,189 @@ function App() { ); } + +export default App; ``` -- Setup navigation for `ListConversationScreen` and `ChatScreen` +### 3. Setup Navigation + +Create a navigation structure for your chat screens: ```javascript +import React from 'react'; +import { createStackNavigator } from '@react-navigation/stack'; +import { ListConversationScreen, ChatScreen } from 'rn-firebase-chat'; + +const Stack = createStackNavigator(); + export const ChatNavigator = () => ( - - + + ); ``` +### 4. Create Your Chat Screens + +#### List Conversations Screen + ```javascript import React, { useCallback } from 'react'; import { ListConversationScreen } from 'rn-firebase-chat'; -import { navigate } from '../../navigation/NavigationService'; -import RouteKey from '../../navigation/RouteKey'; +import { useNavigation } from '@react-navigation/native'; -export const ListChatScreen: React.FC = () => { - const handleItemPress = useCallback((data) => { - navigate(RouteKey.ChatScreen, data); - }, []); +export const ListChatScreen = () => { + const navigation = useNavigation(); - return ; + const handleConversationPress = useCallback((conversation) => { + navigation.navigate('Chat', { + memberIds: conversation.memberIds, + partners: conversation.partners + }); + }, [navigation]); + + return ( + + ); }; ``` +#### Individual Chat Screen + ```javascript import React from 'react'; -import { ChatScreen as BaseChatScreen } from 'rn-firebase-chat'; +import { ChatScreen } from 'rn-firebase-chat'; -const partnerInfo = { - id: 'ayz123', - name: 'Tony', - avatar: 'https://example.com/tony.jpg', -}; +export const ChatScreen = ({ route }) => { + const { memberIds, partners } = route.params; -export const ChatScreen: React.FC = () => { return ( - + console.log('Loading messages...')} + onLoadEnd={() => console.log('Messages loaded')} + sendMessageNotification={() => console.log('New message notification')} + + // Custom Styling + customContainerStyle={{ + backgroundColor: '#f8f9fa', + borderRadius: 12, + }} + customTextStyle={{ + fontSize: 16, + color: '#333333', + }} + + // Input Toolbar Customization + inputToolbarProps={{ + hasCamera: true, + hasGallery: true, + containerStyle: { + backgroundColor: '#ffffff', + borderTopColor: '#e0e0e0', + }, + composerTextInputStyle: { + backgroundColor: '#f5f5f5', + borderRadius: 20, + paddingHorizontal: 15, + } + }} + /> ); }; ``` -## Addons +## 📚 Documentation -Additional features for chat are: +For comprehensive documentation, see the full [Documentation](doc/README.md) here: -#### Image/Video Picker and Camera +- **[Props Reference](doc/PROPS_REFERENCE.md)** - Complete API documentation with all props and interfaces +- **[Advanced Configuration](doc/ADVANCED_CONFIGURATION.md)** - Encryption, environment setup, and performance optimization +- **[Custom Styling](doc/CUSTOM_STYLING.md)** - Theme customization, component styling, and design patterns -This feature will require additional libraries: +### 📋 **Component Overview** -- Using [npm](https://www.npmjs.com/#getting-started): +| Component | Description | Key Features | +|-----------|-------------|--------------| +| **`ChatProvider`** | Main provider for chat context and configuration | Encryption, blacklist filtering, environment prefixes | +| **`ChatScreen`** | Complete chat interface with messaging and media | Real-time messaging, camera, gallery, typing indicators, message status | +| **`ListConversationScreen`** | Conversation list with search functionality | Search bar, custom item renderers, conversation management | +| **`GalleryScreen`** | Media gallery with tabbed interface | Media/Files/Links tabs, custom renderers, full-screen viewing | -```sh -npm install react-native-fast-image react-native-video react-native-vision-camera uuid react-native-image-picker --save -``` +### 🔧 **Available Hooks** -- Using [Yarn](https://yarnpkg.com/): +| Hook | Purpose | Usage | +|------|---------|-------| +| **`useChatContext`** | Access chat context and state | Get user info, chat state, dispatch actions | +| **`useChatSelector`** | Select specific chat state data | Efficiently select and subscribe to state changes | +| **`useTypingIndicator`** | Manage typing indicator behavior | Handle typing start/stop with customizable timeouts | -```sh -yarn add react-native-fast-image react-native-video react-native-vision-camera uuid react-native-image-picker -``` +### đŸ“Ļ **Exported Utilities** -Then using our Addons component in ChatScreen +| Category | Available Utilities | +|----------|-------------------| +| **Date Formatting** | Time formatting, timestamp utilities | +| **Encryption** | AES encryption, key generation, custom encryption support | +| **Message Formatting** | Text formatting, blacklist filtering, message sanitization | +| **Media Handling** | File type detection, media validation, path utilities | +| **Color Utilities** | Color generation, theme helpers | -```javascript -import React from 'react' -import {ChatScreen as BaseChatScreen} from 'rn-firebase-chat' -import {CameraView, useCamera} from 'rn-firebase-chat/src/addons/camera' +### 📨 **Supported Message Types** -... +| Type | Description | Features | +|------|-------------|----------| +| **Text Messages** | Standard text messaging | Encryption support, blacklist filtering, typing indicators | +| **Image Messages** | Photo sharing and viewing | Camera capture, gallery selection, full-screen viewing | +| **Video Messages** | Video sharing and playback | Video recording, thumbnail previews, custom video player | +| **Voice Messages** | Audio message support | Ready for voice message integration | -export const ChatScreen: React.FC = () => { - const {onPressCamera, onPressGallery} = useCamera() - return ( - - {({onSend}) => ( )} - - ) -} +### 📱 **Platform Support** -``` +- ✅ **iOS** - Full feature support including camera and media +- ✅ **Android** - Full feature support including camera and media +- 🔧 **React Native CLI** - Fully supported +- 🔧 **Expo** - Supported with custom development build (camera features require custom build) + + + +## 🤝 Contributing -## Contributing +We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details on how to: -See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. +- Report bugs +- Suggest new features +- Submit pull requests +- Set up the development environment -## License +## 📄 License -MIT +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. --- -Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob) +Built with â¤ī¸ using [create-react-native-library](https://github.com/callstack/react-native-builder-bob) diff --git a/doc/ADVANCED_CONFIGURATION.md b/doc/ADVANCED_CONFIGURATION.md new file mode 100644 index 0000000..2844f07 --- /dev/null +++ b/doc/ADVANCED_CONFIGURATION.md @@ -0,0 +1,432 @@ +# Advanced Configuration + +This document covers advanced configuration options for `rn-firebase-chat`, including encryption, custom functions, and environment-specific settings. + +## Table of Contents + +- [Encryption Setup](#encryption-setup) +- [Environment Configuration](#environment-configuration) +- [Custom Encryption Functions](#custom-encryption-functions) +- [Blacklist Configuration](#blacklist-configuration) +- [Performance Optimization](#performance-optimization) + +## Encryption Setup + +`rn-firebase-chat` supports AES encryption for secure messaging. This feature can be enabled globally for all messages. + +### Basic Encryption + +```javascript +import { ChatProvider } from 'rn-firebase-chat'; + +const userInfo = { + id: 'user123', + name: 'John Doe', + avatar: 'https://example.com/avatar.jpg' +}; + +function App() { + return ( + + + + ); +} +``` + +### Advanced Encryption Options + +```javascript +import { ChatProvider } from 'rn-firebase-chat'; + +const encryptionConfig = { + enableEncrypt: true, + encryptKey: 'your-secret-key-here', + encryptionOptions: { + algorithm: 'aes-256-cbc', + keySize: 256, + ivSize: 16 + } +}; + +function App() { + return ( + + + + ); +} +``` + +## Environment Configuration + +Use the `prefix` prop to configure different environments and separate data between development, staging, and production. + +### Environment-Specific Configuration + +```javascript +import { ChatProvider } from 'rn-firebase-chat'; + +const getEnvironmentConfig = () => { + switch (__DEV__ ? 'development' : process.env.NODE_ENV) { + case 'development': + return { + prefix: 'dev_', + enableEncrypt: false, + blackListWords: [] + }; + case 'staging': + return { + prefix: 'staging_', + enableEncrypt: true, + encryptKey: process.env.STAGING_ENCRYPT_KEY, + blackListWords: ['test', 'debug'] + }; + case 'production': + return { + prefix: 'prod_', + enableEncrypt: true, + encryptKey: process.env.PROD_ENCRYPT_KEY, + blackListWords: ['spam', 'inappropriate', 'offensive'] + }; + default: + return { + prefix: '', + enableEncrypt: false + }; + } +}; + +function App() { + const envConfig = getEnvironmentConfig(); + + return ( + + + + ); +} +``` + +### Data Separation + +The `prefix` prop affects: +- Collection names in Firestore +- Storage paths in Firebase Storage +- Cache keys for local storage + +Example with prefix `'dev_'`: +- Conversations collection: `dev_conversations` +- Messages collection: `dev_messages` +- Storage path: `dev_chat_media/` + +## Custom Encryption Functions + +You can provide custom encryption and decryption functions for specialized use cases. + +### Custom Encryption Implementation + +```javascript +import CryptoJS from 'crypto-js'; + +const customEncryptionFunctions = { + encrypt: async (text, key) => { + try { + const encrypted = CryptoJS.AES.encrypt(text, key).toString(); + return encrypted; + } catch (error) { + console.error('Encryption failed:', error); + throw error; + } + }, + + decrypt: async (encryptedText, key) => { + try { + const decrypted = CryptoJS.AES.decrypt(encryptedText, key); + return decrypted.toString(CryptoJS.enc.Utf8); + } catch (error) { + console.error('Decryption failed:', error); + throw error; + } + } +}; + +function App() { + return ( + + + + ); +} +``` + +### Hybrid Encryption (RSA + AES) + +```javascript +import { RSA } from 'react-native-crypto'; + +const hybridEncryptionFunctions = { + encrypt: async (text, publicKey) => { + // Generate AES key + const aesKey = generateRandomKey(32); + + // Encrypt message with AES + const encryptedMessage = await aesEncrypt(text, aesKey); + + // Encrypt AES key with RSA + const encryptedKey = await RSA.encrypt(aesKey, publicKey); + + return { + message: encryptedMessage, + key: encryptedKey + }; + }, + + decrypt: async (encryptedData, privateKey) => { + // Decrypt AES key with RSA + const aesKey = await RSA.decrypt(encryptedData.key, privateKey); + + // Decrypt message with AES + const decryptedMessage = await aesDecrypt(encryptedData.message, aesKey); + + return decryptedMessage; + } +}; +``` + +## Blacklist Configuration + +Configure word filtering to automatically censor inappropriate content. + +### Basic Blacklist + +```javascript +const blacklistConfig = { + blackListWords: [ + 'spam', + 'inappropriate', + 'offensive', + 'harassment' + ] +}; + + + + +``` + +### Advanced Blacklist with Patterns + +```javascript +const advancedBlacklistConfig = { + blackListWords: [ + // Exact matches + 'spam', + 'inappropriate', + + // Pattern matches (using regex) + '\\b\\w*spam\\w*\\b', // Words containing "spam" + '\\b\\w*offensive\\w*\\b', // Words containing "offensive" + + // Common variations + 'sp@m', + 'sp4m', + 'in@ppropriate' + ] +}; +``` + +### Dynamic Blacklist Management + +```javascript +import { useState, useEffect } from 'react'; + +const DynamicBlacklistApp = () => { + const [blacklistWords, setBlacklistWords] = useState([]); + + useEffect(() => { + // Fetch blacklist from your server + fetchBlacklistFromServer().then(words => { + setBlacklistWords(words); + }); + }, []); + + return ( + + + + ); +}; + +const fetchBlacklistFromServer = async () => { + try { + const response = await fetch('https://your-api.com/blacklist'); + const data = await response.json(); + return data.words; + } catch (error) { + console.error('Failed to fetch blacklist:', error); + return []; + } +}; +``` + +## Performance Optimization + +### Message Pagination + +Configure message loading for optimal performance: + +```javascript + console.log('Loading messages...')} + onLoadEnd={() => console.log('Messages loaded')} +/> +``` + +### Lazy Loading + +```javascript +const LazyChatScreen = ({ route }) => { + const [isReady, setIsReady] = useState(false); + const { memberIds, partners } = route.params; + + useEffect(() => { + // Preload essential data + preloadChatData(memberIds).then(() => { + setIsReady(true); + }); + }, [memberIds]); + + if (!isReady) { + return ; + } + + return ( + + ); +}; +``` + +### Memory Management + +```javascript +const OptimizedChatScreen = ({ route }) => { + const { memberIds, partners } = route.params; + + return ( + + ); +}; +``` + +## Error Handling + +### Encryption Error Handling + +```javascript +const ErrorHandlingChatProvider = ({ children }) => { + const [encryptionError, setEncryptionError] = useState(null); + + const handleEncryptionError = (error) => { + console.error('Encryption error:', error); + setEncryptionError(error); + + // Fallback to unencrypted mode + return false; + }; + + if (encryptionError) { + return ( + + Encryption failed. Using unencrypted mode. + setEncryptionError(null)}> + Retry + + + ); + } + + return ( + + {children} + + ); +}; +``` + +### Network Error Handling + +```javascript +const NetworkAwareChatScreen = ({ route }) => { + const [isOnline, setIsOnline] = useState(true); + const { memberIds, partners } = route.params; + + useEffect(() => { + const unsubscribe = NetInfo.addEventListener(state => { + setIsOnline(state.isConnected); + }); + + return unsubscribe; + }, []); + + if (!isOnline) { + return ( + + You're offline. Messages will be sent when connected. + + ); + } + + return ( + console.log('Loading...')} + onLoadEnd={() => console.log('Loaded')} + /> + ); +}; +``` + +This advanced configuration guide covers the most complex use cases and optimization strategies for `rn-firebase-chat`. For basic usage, refer to the main [README](../README.md) and [Props Reference](./PROPS_REFERENCE.md). \ No newline at end of file diff --git a/doc/CUSTOM_STYLING.md b/doc/CUSTOM_STYLING.md new file mode 100644 index 0000000..4d4b199 --- /dev/null +++ b/doc/CUSTOM_STYLING.md @@ -0,0 +1,914 @@ +# Custom Styling + +This document covers all aspects of customizing the appearance and styling of `rn-firebase-chat` components. + +## Table of Contents + +- [Basic Styling](#basic-styling) +- [Theme Customization](#theme-customization) +- [Component-Specific Styling](#component-specific-styling) +- [Input Toolbar Customization](#input-toolbar-customization) +- [Message Bubble Styling](#message-bubble-styling) +- [Gallery Customization](#gallery-customization) +- [Dark Mode Support](#dark-mode-support) +- [Responsive Design](#responsive-design) + +## Basic Styling + +### ChatScreen Container Styling + +```javascript +import { ChatScreen } from 'rn-firebase-chat'; + +const ChatScreenComponent = ({ route }) => { + const { memberIds, partners } = route.params; + + return ( + + ); +}; +``` + +### ListConversationScreen Styling + +```javascript +import { ListConversationScreen } from 'rn-firebase-chat'; + +const ListConversationScreenComponent = () => { + return ( + + ); +}; +``` + +## Theme Customization + +### Creating a Custom Theme + +```javascript +// theme.js +export const chatTheme = { + colors: { + primary: '#007AFF', + secondary: '#5856D6', + background: '#F2F2F7', + surface: '#FFFFFF', + text: '#000000', + textSecondary: '#8E8E93', + border: '#C6C6C8', + success: '#34C759', + error: '#FF3B30', + warning: '#FF9500' + }, + typography: { + title: { + fontSize: 18, + fontWeight: '600' + }, + body: { + fontSize: 16, + fontWeight: '400' + }, + caption: { + fontSize: 14, + fontWeight: '400' + }, + small: { + fontSize: 12, + fontWeight: '400' + } + }, + spacing: { + xs: 4, + sm: 8, + md: 16, + lg: 24, + xl: 32 + }, + borderRadius: { + sm: 4, + md: 8, + lg: 12, + xl: 16 + } +}; + +// Using the theme +const ThemedChatScreen = ({ route }) => { + const { memberIds, partners } = route.params; + + return ( + + ); +}; +``` + +### Theme Provider Pattern + +```javascript +import React, { createContext, useContext } from 'react'; + +const ThemeContext = createContext(); + +export const ThemeProvider = ({ children, theme }) => { + return ( + + {children} + + ); +}; + +export const useTheme = () => { + const theme = useContext(ThemeContext); + if (!theme) { + throw new Error('useTheme must be used within a ThemeProvider'); + } + return theme; +}; + +// App.js +const App = () => { + return ( + + + + + + ); +}; + +// Using theme in components +const ThemedComponent = () => { + const theme = useTheme(); + + return ( + + ); +}; +``` + +## Component-Specific Styling + +### ChatScreen Advanced Styling + +```javascript +const AdvancedChatScreen = ({ route }) => { + const { memberIds, partners } = route.params; + + return ( + + ); +}; +``` + +### Message Status Customization + +```javascript +const CustomMessageStatus = ({ hasUnread }) => { + const theme = useTheme(); + + return ( + + {hasUnread ? ( + + + New + + + ) : ( + + + ✓✓ + + + )} + + ); +}; + +const styles = StyleSheet.create({ + statusContainer: { + flexDirection: 'row', + alignItems: 'center', + marginTop: 4 + }, + unreadIndicator: { + paddingHorizontal: 8, + paddingVertical: 2, + borderRadius: 10, + minWidth: 20, + alignItems: 'center' + }, + unreadText: { + fontSize: 10, + fontWeight: '600' + }, + readIndicator: { + paddingHorizontal: 4 + }, + readText: { + fontSize: 12 + } +}); + +// Using custom message status + +``` + +## Input Toolbar Customization + +### Basic Input Toolbar Styling + +```javascript +const inputToolbarConfig = { + hasCamera: true, + hasGallery: true, + containerStyle: { + backgroundColor: '#ffffff', + borderTopWidth: 1, + borderTopColor: '#e0e0e0', + paddingHorizontal: 16, + paddingVertical: 12 + }, + composeWrapperStyle: { + backgroundColor: '#f8f9fa', + borderRadius: 20, + paddingHorizontal: 16, + paddingVertical: 8, + flex: 1, + marginRight: 12 + }, + composerTextInputStyle: { + fontSize: 16, + color: '#333333', + paddingVertical: 8, + maxHeight: 100 + }, + iconStyle: { + width: 24, + height: 24, + tintColor: '#007AFF' + } +}; + + +``` + +### Advanced Input Toolbar with Custom Views + +```javascript +const AdvancedInputToolbar = () => { + const [isRecording, setIsRecording] = useState(false); + const [isTyping, setIsTyping] = useState(false); + + const renderLeftCustomView = () => ( + + console.log('Attach pressed')} + > + 📎 + + console.log('Emoji pressed')} + > + 😊 + + + ); + + const renderRightCustomView = () => ( + + {isTyping ? ( + setIsRecording(!isRecording)} + > + 🎤 + + ) : ( + console.log('Send pressed')} + > + 📤 + + )} + + ); + + const inputToolbarProps = { + hasCamera: true, + hasGallery: true, + containerStyle: { + backgroundColor: '#ffffff', + borderTopWidth: 1, + borderTopColor: '#e0e0e0', + paddingHorizontal: 16, + paddingVertical: 12, + flexDirection: 'row', + alignItems: 'center' + }, + composeWrapperStyle: { + backgroundColor: '#f8f9fa', + borderRadius: 20, + paddingHorizontal: 16, + paddingVertical: 8, + flex: 1, + marginHorizontal: 8 + }, + composerTextInputStyle: { + fontSize: 16, + color: '#333333', + paddingVertical: 8, + maxHeight: 100 + }, + renderLeftCustomView, + renderRightCustomView + }; + + return ( + + ); +}; + +const styles = StyleSheet.create({ + leftToolbar: { + flexDirection: 'row', + alignItems: 'center' + }, + rightToolbar: { + flexDirection: 'row', + alignItems: 'center' + }, + attachButton: { + padding: 8, + marginRight: 8 + }, + emojiButton: { + padding: 8 + }, + voiceButton: { + padding: 8, + backgroundColor: '#FF3B30', + borderRadius: 20, + width: 40, + height: 40, + alignItems: 'center', + justifyContent: 'center' + }, + sendButton: { + padding: 8, + backgroundColor: '#007AFF', + borderRadius: 20, + width: 40, + height: 40, + alignItems: 'center', + justifyContent: 'center' + }, + attachIcon: { + fontSize: 20 + }, + emojiIcon: { + fontSize: 20 + }, + voiceIcon: { + fontSize: 16, + color: '#ffffff' + }, + sendIcon: { + fontSize: 16, + color: '#ffffff' + } +}); +``` + +## Message Bubble Styling + +### Custom Message Bubble Components + +```javascript +const CustomMessageBubble = ({ message, position }) => { + const theme = useTheme(); + const isOwnMessage = position === 'right'; + + const bubbleStyle = { + backgroundColor: isOwnMessage ? theme.colors.primary : theme.colors.surface, + borderRadius: theme.borderRadius.lg, + paddingHorizontal: theme.spacing.md, + paddingVertical: theme.spacing.sm, + marginVertical: theme.spacing.xs, + maxWidth: '80%', + alignSelf: isOwnMessage ? 'flex-end' : 'flex-start', + shadowColor: '#000', + shadowOffset: { + width: 0, + height: 1, + }, + shadowOpacity: 0.1, + shadowRadius: 2, + elevation: 2 + }; + + const textStyle = { + color: isOwnMessage ? theme.colors.surface : theme.colors.text, + fontSize: theme.typography.body.fontSize, + lineHeight: 22 + }; + + return ( + + {message.text} + + {formatTime(message.createdAt)} + + + ); +}; + +const styles = StyleSheet.create({ + timestamp: { + fontSize: 12, + marginTop: 4, + alignSelf: 'flex-end' + } +}); + +// Using custom message bubble + +``` + +## Gallery Customization + +### Custom Gallery Header + +```javascript +const CustomGalleryHeader = () => { + const theme = useTheme(); + + return ( + + + + Shared Media + + + Tap to view full size + + + + ✕ + + + ); +}; + +const styles = StyleSheet.create({ + galleryHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 20, + paddingVertical: 16, + borderBottomWidth: 1, + borderBottomColor: '#e0e0e0' + }, + headerContent: { + flex: 1 + }, + galleryTitle: { + fontSize: 18, + fontWeight: '600', + marginBottom: 4 + }, + gallerySubtitle: { + fontSize: 14 + }, + closeButton: { + padding: 8 + }, + closeIcon: { + fontSize: 20, + fontWeight: '600' + } +}); + +// Using custom gallery header + +``` + +### Custom Media Items + +```javascript +const CustomMediaItem = ({ item, index }) => { + const theme = useTheme(); + + if (item.type === 'image') { + return ( + + + + + {item.name} + + + + ); + } + + if (item.type === 'video') { + return ( + + + + + â–ļī¸ + + + + {item.name} + + + ); + } + + return null; +}; + +const styles = StyleSheet.create({ + mediaItem: { + margin: 8, + borderRadius: 8, + overflow: 'hidden' + }, + mediaImage: { + width: 120, + height: 120 + }, + mediaOverlay: { + position: 'absolute', + bottom: 0, + left: 0, + right: 0, + backgroundColor: 'rgba(0,0,0,0.5)', + padding: 8 + }, + mediaCaption: { + fontSize: 12, + fontWeight: '500' + }, + videoContainer: { + width: 120, + height: 120, + position: 'relative' + }, + videoThumbnail: { + width: '100%', + height: '100%' + }, + playButton: { + position: 'absolute', + top: '50%', + left: '50%', + transform: [{ translateX: -15 }, { translateY: -15 }], + width: 30, + height: 30, + backgroundColor: 'rgba(0,0,0,0.7)', + borderRadius: 15, + alignItems: 'center', + justifyContent: 'center' + }, + playIcon: { + fontSize: 16 + } +}); + +// Using custom media items + +``` + +## Dark Mode Support + +### Dark Theme Configuration + +```javascript +import { useColorScheme } from 'react-native'; + +const darkTheme = { + colors: { + primary: '#0A84FF', + secondary: '#5E5CE6', + background: '#000000', + surface: '#1C1C1E', + text: '#FFFFFF', + textSecondary: '#8E8E93', + border: '#38383A', + success: '#30D158', + error: '#FF453A', + warning: '#FF9F0A' + }, + // ... rest of theme +}; + +const lightTheme = { + colors: { + primary: '#007AFF', + secondary: '#5856D6', + background: '#F2F2F7', + surface: '#FFFFFF', + text: '#000000', + textSecondary: '#8E8E93', + border: '#C6C6C8', + success: '#34C759', + error: '#FF3B30', + warning: '#FF9500' + }, + // ... rest of theme +}; + +const ThemeAwareApp = () => { + const colorScheme = useColorScheme(); + const theme = colorScheme === 'dark' ? darkTheme : lightTheme; + + return ( + + + + + + ); +}; +``` + +### Dark Mode Chat Screen + +```javascript +const DarkModeChatScreen = ({ route }) => { + const theme = useTheme(); + const { memberIds, partners } = route.params; + + return ( + + ); +}; +``` + +## Responsive Design + +### Responsive Chat Screen + +```javascript +import { Dimensions } from 'react-native'; + +const ResponsiveChatScreen = ({ route }) => { + const { width, height } = Dimensions.get('window'); + const { memberIds, partners } = route.params; + + const isTablet = width > 768; + const isLandscape = width > height; + + const responsiveStyles = { + container: { + backgroundColor: '#f8f9fa', + flex: 1, + paddingHorizontal: isTablet ? 20 : 10 + }, + messageContainer: { + backgroundColor: '#ffffff', + marginVertical: isTablet ? 4 : 2, + borderRadius: isTablet ? 16 : 12, + paddingHorizontal: isTablet ? 20 : 16, + paddingVertical: isTablet ? 16 : 12 + }, + textStyle: { + fontSize: isTablet ? 18 : 16, + lineHeight: isTablet ? 26 : 22 + } + }; + + return ( + + ); +}; +``` + +### Adaptive Layout + +```javascript +const AdaptiveLayout = () => { + const { width } = Dimensions.get('window'); + const isTablet = width > 768; + + if (isTablet) { + return ( + + + + + + + + + ); + } + + return ( + + + + + ); +}; + +const styles = StyleSheet.create({ + tabletLayout: { + flex: 1, + flexDirection: 'row' + }, + sidebar: { + width: 320, + borderRightWidth: 1, + borderRightColor: '#e0e0e0' + }, + chatArea: { + flex: 1 + } +}); +``` + +This comprehensive styling guide covers all aspects of customizing the appearance of `rn-firebase-chat` components. For basic usage and API reference, see the main [README](../README.md) and [Props Reference](./PROPS_REFERENCE.md). \ No newline at end of file diff --git a/doc/PROPS_REFERENCE.md b/doc/PROPS_REFERENCE.md new file mode 100644 index 0000000..e8589ad --- /dev/null +++ b/doc/PROPS_REFERENCE.md @@ -0,0 +1,529 @@ +# Props Reference + +This document provides detailed information about all components, props, and interfaces available in `rn-firebase-chat`. + +## Table of Contents + +- [ChatProvider](#chatprovider) +- [ChatScreen](#chatscreen) +- [ListConversationScreen](#listconversationscreen) +- [GalleryScreen](#galleryscreen) +- [IInputToolbar](#iinputtoolbar) +- [Interfaces](#interfaces) + +## ChatProvider + +The main provider component that manages chat context and configurations. This component must wrap your entire app to provide chat functionality. + +### Required Props + +| Prop Name | Type | Description | +|-----------|------|-------------| +| `userInfo` | `IUserInfo` | Current user information object with `id`, `name`, and `avatar` | +| `children` | `React.ReactNode` | React children elements | + +### Optional Props + +> For advanced configuration options (such as encryption, environment prefixes, and custom encryption functions), see the [Advanced Configuration](./ADVANCED_CONFIGURATION.md) documentation. + +| Prop Name | Type | Default | Description | +|-----------|------|---------|-------------| +| `enableEncrypt` | `boolean` | `false` | Enables message encryption using AES | +| `encryptKey` | `string` | `''` | Encryption key for secure messages | +| `blackListWords` | `string[]` | `[]` | Array of words to filter out from messages | +| `encryptionOptions` | `EncryptionOptions` | - | Advanced encryption configuration | +| `encryptionFuncProps` | `EncryptionFunctions` | - | Custom encryption functions | +| `prefix` | `string` | `''` | Prefix for different environments (dev/stage/prod) | + +### Example + +```javascript +import { ChatProvider } from 'rn-firebase-chat'; + +const userInfo = { + id: 'user123', + name: 'John Doe', + avatar: 'https://example.com/avatar.jpg' +}; + +function App() { + return ( + + + + ); +} +``` + +## ChatScreen + +The main chat interface component for displaying and sending messages. This component handles real-time messaging, media sharing, and message status. + +### Required Props + +| Prop Name | Type | Description | +|-----------|------|-------------| +| `memberIds` | `string[]` | Array of member IDs in the chat | +| `partners` | `IUserInfo[]` | Array of user information for chat partners | + +### Optional Props + +| Prop Name | Type | Default | Description | +|-----------|------|---------|-------------| +| `style` | `StyleProp` | - | Custom style for the chat screen container | +| `hasCamera` | `boolean` | `false` | Enable camera functionality | +| `hasGallery` | `boolean` | `false` | Enable gallery functionality | +| `enableTyping` | `boolean` | `false` | Enable typing indicators | +| `messageStatusEnable` | `boolean` | `false` | Enable message status indicators | +| `maxPageSize` | `number` | `20` | Maximum number of messages to load per page | +| `typingTimeoutSeconds` | `number` | `3` | Timeout for typing indicator in seconds | +| `timeoutSendNotify` | `number` | `3` | Timeout for sending notifications in seconds | +| `inputToolbarProps` | `IInputToolbar` | - | Props for customizing the input toolbar | +| `customContainerStyle` | `StyleProp` | - | Custom style for the message container | +| `customTextStyle` | `StyleProp` | - | Custom style for text messages | +| `onStartLoad` | `() => void` | - | Callback function when loading starts | +| `onLoadEnd` | `() => void` | - | Callback function when loading ends | +| `onPressCamera` | `() => void` | - | Callback function for camera button press | +| `sendMessageNotification` | `() => void` | - | Callback function to send notification | +| `customMessageStatus` | `(hasUnread: boolean) => JSX.Element` | - | Custom component for message status | +| `unReadSentMessage` | `string` | - | Custom text for unread sent message | +| `unReadSeenMessage` | `string` | - | Custom text for unread seen message | +| `customImageVideoBubbleProps` | `CustomImageVideoBubbleProps` | - | Custom props for image and video bubbles | +| `customConversationInfo` | `CustomConversationInfo` | - | Custom information for the conversation | +| `iconsCamera` | `IconPaths` | - | Paths for various camera icons | + +### Example + +```javascript +import { ChatScreen } from 'rn-firebase-chat'; + +const ChatScreenComponent = ({ route }) => { + const { memberIds, partners } = route.params; + + const handleStartLoad = () => { + console.log('Loading messages...'); + }; + + const handleLoadEnd = () => { + console.log('Messages loaded'); + }; + + return ( + + ); +}; +``` + +## ListConversationScreen + +Displays a list of conversations with optional search functionality. This component shows all conversations for the current user. + +### Props + +| Prop Name | Type | Default | Description | +|-----------|------|---------|-------------| +| `hasSearchBar` | `boolean` | `false` | Enable search bar for filtering conversations | +| `onPress` | `(conversation: ConversationProps) => void` | - | Callback function when a conversation is pressed | +| `renderCustomItem` | `({ item, index }: ListItem) => JSX.Element` | - | Function to render custom conversation items | +| `conversationItemProps` | `Omit` | - | Props for customizing conversation items | + +### Example + +```javascript +import { ListConversationScreen } from 'rn-firebase-chat'; + +const ListConversationScreenComponent = () => { + const navigation = useNavigation(); + + const handleConversationPress = (conversation) => { + navigation.navigate('Chat', { + memberIds: conversation.memberIds, + partners: conversation.partners + }); + }; + + const renderCustomItem = ({ item, index }) => { + return ( + + {item.name} + {item.lastMessage} + + ); + }; + + return ( + + ); +}; +``` + +## GalleryScreen + +Modal component for displaying media, files, and links shared in conversations. This component provides a gallery view for all shared content. + +### Props + +| Prop Name | Type | Description | +|-----------|------|-------------| +| `renderCustomHeader` | `() => JSX.Element` | Function to render custom header for the gallery modal | +| `renderCustomMedia` | `({ item, index }: MediaItem) => JSX.Element` | Function to render custom media items (images/videos) | +| `renderCustomFile` | `() => JSX.Element` | Function to render custom file items (documents) | +| `renderCustomLink` | `() => JSX.Element` | Function to render custom link items | +| `iconCloseModal` | `ImageRequireSource` | Icon to display for closing the modal | +| `customSlider` | `(currentTime: number, duration: number, paused: boolean, videoRef: VideoRef) => React.ReactNode` | Custom video slider component | +| `headerStyle` | `StyleProp` | Custom style for the header of the modal | +| `tabStyle` | `StyleProp` | Custom style for the tabs in the modal | +| `activeTabStyle` | `StyleProp` | Custom style for the active tab in the modal | +| `tabTextStyle` | `StyleProp` | Custom style for the tab text | +| `activeTabTextStyle` | `StyleProp` | Custom style for the text of the active tab | +| `tabIndicatorStyle` | `StyleProp` | Custom style for the tab indicator | +| `containerStyle` | `StyleProp` | Custom style for the main container of the modal | + +### Example + +```javascript +import { GalleryScreen } from 'rn-firebase-chat'; + +const GalleryScreenComponent = () => { + const renderCustomHeader = () => ( + + Shared Media + + ); + + const renderCustomMedia = ({ item, index }) => ( + + + {item.name} + + ); + + return ( + + ); +}; +``` + +## IInputToolbar + +Configuration object for customizing the input toolbar. This interface allows you to customize the appearance and behavior of the message input area. + +### Properties + +| Prop Name | Type | Description | +|-----------|------|-------------| +| `hasCamera` | `boolean` | Indicates whether the camera option is enabled | +| `hasGallery` | `boolean` | Indicates whether the gallery option is enabled | +| `onPressCamera` | `() => void` | Callback function triggered when the camera icon is pressed | +| `onPressGallery` | `() => void` | Callback function triggered when the gallery icon is pressed | +| `containerStyle` | `StyleProp` | Custom style for the toolbar container | +| `composeWrapperStyle` | `StyleProp` | Custom style for the compose wrapper | +| `composerTextInputStyle` | `StyleProp` | Custom style for the composer text input | +| `customViewStyle` | `StyleProp` | Custom style for the custom view | +| `cameraIcon` | `string` | Icon path for the camera button | +| `galleryIcon` | `string` | Icon path for the gallery button | +| `iconSend` | `string` | Icon path for the send button | +| `iconStyle` | `StyleProp` | Custom style for the icons | +| `renderLeftCustomView` | `() => React.ReactNode` | Function to render a custom view on the left side of the toolbar | +| `renderRightCustomView` | `() => React.ReactNode` | Function to render a custom view on the right side of the toolbar | + +### Example + +```javascript +const inputToolbarConfig = { + hasCamera: true, + hasGallery: true, + onPressCamera: () => { + console.log('Camera pressed'); + }, + onPressGallery: () => { + console.log('Gallery pressed'); + }, + containerStyle: { + backgroundColor: '#ffffff', + borderTopWidth: 1, + borderTopColor: '#e0e0e0', + paddingHorizontal: 10, + paddingVertical: 5 + }, + composerTextInputStyle: { + backgroundColor: '#f8f9fa', + borderRadius: 20, + paddingHorizontal: 15, + paddingVertical: 8, + fontSize: 16 + }, + cameraIcon: require('./assets/camera.png'), + galleryIcon: require('./assets/gallery.png'), + iconSend: require('./assets/send.png'), + renderLeftCustomView: () => ( + + 📎 + + ) +}; + + +``` + +## Interfaces + +### IUserInfo + +Interface for user information objects. + +```typescript +interface IUserInfo { + id: string; + name: string; + avatar?: string; + image?: string; // Alternative to avatar +} +``` + +### ConversationProps + +Interface for conversation data. + +```typescript +interface ConversationProps { + id: string; + memberIds: string[]; + partners: IUserInfo[]; + lastMessage?: string; + lastMessageTime?: Date; + unreadCount?: number; +} +``` + +### ListItem + +Interface for list item data. + +```typescript +interface ListItem { + item: ConversationProps; + index: number; +} +``` + +### MediaItem + +Interface for media item data. + +```typescript +interface MediaItem { + item: { + id: string; + url: string; + name: string; + type: 'image' | 'video' | 'file' | 'link'; + }; + index: number; +} +``` + +### EncryptionOptions + +Interface for encryption configuration. + +```typescript +interface EncryptionOptions { + algorithm?: string; + keySize?: number; + ivSize?: number; +} +``` + +### EncryptionFunctions + +Interface for custom encryption functions. + +```typescript +interface EncryptionFunctions { + encrypt?: (text: string, key: string) => Promise; + decrypt?: (encryptedText: string, key: string) => Promise; +} +``` + +### CustomImageVideoBubbleProps + +Interface for custom image/video bubble configuration. + +```typescript +interface CustomImageVideoBubbleProps { + imageStyle?: StyleProp; + videoStyle?: StyleProp; + playButtonStyle?: StyleProp; + thumbnailStyle?: StyleProp; +} +``` + +### CustomConversationInfo + +Interface for custom conversation information. + +```typescript +interface CustomConversationInfo { + title?: string; + subtitle?: string; + avatar?: string; + status?: 'online' | 'offline' | 'away'; +} +``` + +### IconPaths + +Interface for camera icon paths. + +```typescript +interface IconPaths { + camera?: string; + flashOn?: string; + flashOff?: string; + switchCamera?: string; + close?: string; +} +``` + +### VideoRef + +Type for video reference. + +```typescript +type VideoRef = React.RefObject; +``` + +## Advanced Usage Examples + +### Custom Message Status Component + +```javascript +const CustomMessageStatus = ({ hasUnread }) => ( + + {hasUnread ? ( + + New + + ) : ( + ✓✓ + )} + +); + + +``` + +### Custom Input Toolbar with Additional Features + +```javascript +const CustomInputToolbar = () => { + const [isRecording, setIsRecording] = useState(false); + + const inputToolbarProps = { + hasCamera: true, + hasGallery: true, + renderRightCustomView: () => ( + + setIsRecording(!isRecording)} + style={[styles.recordButton, isRecording && styles.recording]} + > + {isRecording ? 'âšī¸' : '🎤'} + + + ), + containerStyle: { + backgroundColor: '#f0f0f0', + paddingHorizontal: 15, + paddingVertical: 10 + } + }; + + return ( + + ); +}; +``` + +### Custom Gallery with Filtering + +```javascript +const CustomGallery = () => { + const renderCustomMedia = ({ item, index }) => { + if (item.type === 'image') { + return ( + + + {item.name} + + ); + } + return null; + }; + + return ( + ( + + Shared Images + Tap to view full size + + )} + /> + ); +}; +``` + +This API reference provides comprehensive documentation for all components and interfaces in the `rn-firebase-chat` library. For additional examples and use cases, refer to the main README file. \ No newline at end of file diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000..033ff3e --- /dev/null +++ b/doc/README.md @@ -0,0 +1,73 @@ +# Documentation + +Welcome to the `rn-firebase-chat` documentation! This folder contains detailed documentation for all aspects of the library. + +## 📖 Documentation Index + +### [Props Reference](./PROPS_REFERENCE.md) +Complete API documentation including: +- All component props and interfaces +- Detailed examples for each component +- Advanced usage patterns +- TypeScript definitions + +### [Advanced Configuration](./ADVANCED_CONFIGURATION.md) +Advanced setup and configuration including: +- Encryption setup and security best practices +- Environment-specific configuration +- Custom encryption functions +- Performance optimization +- Error handling strategies + +### [Custom Styling](./CUSTOM_STYLING.md) +Comprehensive styling guide including: +- Theme customization and theming patterns +- Component-specific styling +- Input toolbar customization +- Message bubble styling +- Gallery customization +- Dark mode support +- Responsive design patterns + +## 🚀 Getting Started + +If you're new to `rn-firebase-chat`, start with the main [README](../README.md) file for: +- Installation instructions +- Quick start guide +- Basic usage examples +- Feature overview + +## 📚 What's Included + +### Components +- **ChatProvider** - Main context provider for chat functionality +- **ChatScreen** - Complete chat interface with messaging and media +- **ListConversationScreen** - Conversation list with search +- **GalleryScreen** - Media gallery for shared content + +### Features +- Real-time messaging with Firebase +- Media sharing (images, videos, files) +- Message encryption +- Typing indicators +- Message status tracking +- Customizable UI components +- Search functionality +- Content filtering + +## 🔗 Quick Links + +- [Main README](../README.md) - Installation and quick start +- [Props Reference](./PROPS_REFERENCE.md) - Complete API documentation +- [Advanced Configuration](./ADVANCED_CONFIGURATION.md) - Advanced setup and optimization +- [Custom Styling](./CUSTOM_STYLING.md) - Styling and theming guide +- [Contributing Guide](../CONTRIBUTING.md) - How to contribute +- [License](../LICENSE) - MIT License + +## 💡 Need Help? + +If you can't find what you're looking for in the documentation: +1. Check the [API Reference](./API_REFERENCE.md) for detailed component documentation +2. Look at the examples in the main [README](../README.md) +3. Open an issue on GitHub for bugs or feature requests +4. Check the contributing guide for development setup \ No newline at end of file diff --git a/src/chat/ChatScreen.tsx b/src/chat/ChatScreen.tsx index f9e0219..d56ad27 100644 --- a/src/chat/ChatScreen.tsx +++ b/src/chat/ChatScreen.tsx @@ -6,20 +6,14 @@ import React, { useRef, useState, } from 'react'; -import { - KeyboardAvoidingView, - type StyleProp, - StyleSheet, - View, - type ViewStyle, -} from 'react-native'; -import { - type ComposerProps, - GiftedChat, - Bubble, +import { KeyboardAvoidingView, StyleSheet, View } from 'react-native'; +import type { StyleProp, ViewStyle } from 'react-native'; +import { GiftedChat } from 'react-native-gifted-chat'; +import type { + ComposerProps, + GiftedChatProps, + BubbleProps, } from 'react-native-gifted-chat'; -import type { GiftedChatProps } from 'react-native-gifted-chat/lib/GiftedChat/types'; -import type { BubbleProps } from 'react-native-gifted-chat/lib/Bubble/types'; import TypingIndicator from 'react-native-gifted-chat/lib/TypingIndicator'; import { FirestoreServices } from '../services/firebase'; import type { @@ -64,7 +58,7 @@ interface ChatScreenProps extends GiftedChatProps { enableTyping?: boolean; typingTimeoutSeconds?: number; messageStatusEnable?: boolean; - customMessageStatus?: (hasUnread: boolean) => React.JSX.Element; + customMessageStatus?: (hasUnread: boolean) => JSX.Element; children?: (props: ChildrenProps) => ReactNode | ReactNode; }