# @acorex/components/conversation

A modern, fully-featured conversation/chat component for Angular 18+. Built with signals, standalone components, and extensibility in mind.

## 🚀 Features

- **Real-time Messaging** - Live message updates with WebSocket support
- **Multiple Message Types** - Text, images, videos, audio, voice, files, locations, stickers, contacts
- **Rich Interactions** - Reactions, replies, message editing, deletion, forwarding
- **Group & Private Chats** - Support for 1-on-1 and group conversations
- **Typing Indicators** - Real-time typing status
- **Read Receipts** - Message delivery and read status
- **Infinite Scroll** - Efficient pagination for message history
- **Search** - Search within conversations and messages
- **Extensible** - Plugin system for custom message renderers and actions
- **Responsive** - Mobile-friendly design
- **Accessibility** - ARIA labels and keyboard navigation

## 📦 Installation

```bash
npm install @acorex/components/conversation
```

## 🔧 Peer Dependencies

This package requires the following peer dependencies:

### Required Angular Dependencies

```json
{
  "@angular/common": "^18.0.0",
  "@angular/core": "^18.0.0",
  "@angular/forms": "^18.0.0",
  "rxjs": "^7.8.0"
}
```

### Required Acorex Dependencies

#### Core Packages

- `@acorex/cdk/common` - Common utilities and directives
- `@acorex/core/date-time` - Date and time formatting
- `@acorex/core/format` - General formatting utilities

#### Component Packages

- `@acorex/components/avatar` - User avatars
- `@acorex/components/badge` - Notification badges
- `@acorex/components/button` - Button components
- `@acorex/components/decorators` - Decorative elements
- `@acorex/components/dialog` - Dialog service
- `@acorex/components/dropdown` - Dropdown panels
- `@acorex/components/image` - Image components
- `@acorex/components/label` - Label components
- `@acorex/components/loading` - Loading indicators
- `@acorex/components/menu` - Context menus
- `@acorex/components/popover` - Popover components
- `@acorex/components/popup` - Popup service
- `@acorex/components/search-box` - Search functionality
- `@acorex/components/select-box` - Select dropdowns
- `@acorex/components/tabs` - Tab components
- `@acorex/components/text-area` - Text input areas
- `@acorex/components/text-box` - Text input boxes
- `@acorex/components/toast` - Toast notifications
- `@acorex/components/tooltip` - Tooltips
- `@acorex/components/uploader` - File upload functionality

## 🎯 Quick Start

> **New to conversation?** Check out our [5-Minute Quick Start Guide](./docs/QUICK-START.md) for the fastest way to get started!

### Detailed Setup

### 1. Standalone Application (Recommended)

```typescript
import { ApplicationConfig } from '@angular/core';
import {
  provideConversation,
  AXIndexedDBUserApi,
  AXIndexedDBConversationApi,
  AXIndexedDBMessageApi,
  AXIndexedDBRealtimeApi,
} from '@acorex/components/conversation';

export const appConfig: ApplicationConfig = {
  providers: [
    MyAppUploaderService,
    provideConversation({
      userApi: AXIndexedDBUserApi,
      conversationApi: AXIndexedDBConversationApi,
      messageApi: AXIndexedDBMessageApi,
      realtimeApi: AXIndexedDBRealtimeApi, // optional
      config: {
        messagePageSize: 50,
        conversationPageSize: 30,
      },
      registry: {
        // Optional: Register custom message renderers, actions, etc.
      },
    }),
  ],
};
```

### 2. NgModule Application (Legacy)

```typescript
import { NgModule } from '@angular/core';
import {
  AXConversationModule,
  AXIndexedDBUserApi,
  AXIndexedDBConversationApi,
  AXIndexedDBMessageApi,
  AXIndexedDBRealtimeApi,
} from '@acorex/components/conversation';

@NgModule({
  imports: [
    AXConversationModule.forRoot({
      userApi: AXIndexedDBUserApi,
      conversationApi: AXIndexedDBConversationApi,
      messageApi: AXIndexedDBMessageApi,
      realtimeApi: AXIndexedDBRealtimeApi,
      config: { /* ... */ },
    }),
  ],
})
export class AppModule {}
```

### 3. Use in Template

```html
<ax-conversation-container></ax-conversation-container>
```

## 🔌 API Implementation

You must provide an API implementation that extends `AXConversationApi`:

```typescript
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { AXConversationApi, AXConversationPagination, AXConversationPaginatedResult } from '@acorex/components/conversation';

@Injectable()
export class MyConversationApi extends AXConversationApi {
  constructor(private http: HttpClient) {
    super();
  }

  async connect(): Promise<void> {
    // Initialize WebSocket connection
  }

  async fetchConversations(pagination: AXConversationPagination): Promise<AXConversationPaginatedResult<AXConversation>> {
    const response = await this.http.get('/api/conversations', {
      params: { page: pagination.page, pageSize: pagination.pageSize }
    }).toPromise();
    return response;
  }

  // Implement other required methods...
}
```

### Built-in API Implementations

#### IndexedDB API (Development/Demo)

```typescript
import {
  provideConversation,
  AXIndexedDBUserApi,
  AXIndexedDBConversationApi,
  AXIndexedDBMessageApi,
  AXIndexedDBRealtimeApi,
} from '@acorex/components/conversation';

// Provides in-memory storage with sample data
// Perfect for development and demos
provideConversation({
  userApi: AXIndexedDBUserApi,
  conversationApi: AXIndexedDBConversationApi,
  messageApi: AXIndexedDBMessageApi,
  realtimeApi: AXIndexedDBRealtimeApi,
});
```

Register a service that subscribes to `AXUploaderService.onUpload`, `onResolveUrl`, and `onDeleteMedia` (see showcase `AXShowcaseConversationIndexedDbUploaderService`).

#### IndexedDB with AI API (AI-Powered Demo)

```typescript
import {
  provideConversation,
  AXIndexedDBUserApi,
  AXIndexedDBConversationApi,
  AXIndexedDBMessageAIApi,
  AXIndexedDBRealtimeApi,
} from '@acorex/components/conversation';

// Includes AI-powered auto-responses via message API
provideConversation({
  userApi: AXIndexedDBUserApi,
  conversationApi: AXIndexedDBConversationApi,
  messageApi: AXIndexedDBMessageAIApi,
  realtimeApi: AXIndexedDBRealtimeApi,
});
```

## ⚙️ Configuration

### Conversation Config

```typescript
interface AXConversationConfig {
  // Pagination
  messagePageSize?: number;             // Default: 50
  conversationPageSize?: number;        // Default: 30
  infiniteScrollThreshold?: number;     // Default: 200px
  scrollThreshold?: number;             // Default: 100px

  // UI Behavior
  messageHighlightDuration?: number;    // Default: 2000ms
  typingIndicatorTimeout?: number;      // Default: 3000ms
}
```

### Registry Configuration

```typescript
interface AXConversationRegistryConfiguration {
  messageRenderers?: AXConversationMessageRenderer[];
  messageActions?: AXConversationMessageAction[];
  composerActions?: AXConversationComposerAction[];
  composerTabs?: AXConversationComposerTab[];
  conversationTabs?: AXConversationTab[];
  infoBarActions?: AXConversationInfoBarAction[];
  conversationItemActions?: AXConversationItemAction[];
}
```

## 🎨 Customization

### Custom Message Renderer

```typescript
import { Component, input } from '@angular/core';
import { AXConversationMessageRenderer } from '@acorex/components/conversation';

@Component({
  selector: 'my-custom-renderer',
  template: `<div>{{ message().payload.customData }}</div>`
})
export class MyCustomRendererComponent {
  message = input.required<AXConversationMessage>();
}

const myRenderer: AXConversationMessageRenderer = {
  type: 'custom',
  component: MyCustomRendererComponent,
  priority: 100
};

// Register in config
provideConversation({
  api: MyApi,
  registry: {
    messageRenderers: [myRenderer]
  }
});
```

### Custom Message Action

```typescript
const forwardAction: AXConversationMessageAction = {
  id: 'forward',
  label: 'Forward',
  icon: 'forward',
  shortcut: 'Ctrl+F',
  enabled: (message, user) => message.senderId === user.id,
  execute: async (message, service) => {
    // Forward logic
  }
};

provideConversation({
  api: MyApi,
  registry: {
    messageActions: [forwardAction]
  }
});
```

## 📱 Components

### Main Components

- `<ax-conversation-container>` - Full conversation UI with sidebar, messages, and composer
- `<ax-conversation-sidebar>` - Conversation list sidebar
- `<ax-conversation-message-list>` - Message list with virtual scrolling
- `<ax-conversation-composer>` - Message input area
- `<ax-conversation-info-bar>` - Conversation header with actions

### Usage Examples

```html
<!-- Full conversation UI -->
<ax-conversation-container></ax-conversation-container>

<!-- Custom layout -->
<div class="my-chat-layout">
  <ax-conversation-sidebar></ax-conversation-sidebar>
  <div class="chat-main">
    <ax-conversation-info-bar></ax-conversation-info-bar>
    <ax-conversation-message-list></ax-conversation-message-list>
    <ax-conversation-composer></ax-conversation-composer>
  </div>
</div>
```

## 🎭 Services

### AXConversationService

Main service for conversation operations:

```typescript
import { inject } from '@angular/core';
import { AXConversationService } from '@acorex/components/conversation';

export class MyComponent {
  private conversationService = inject(AXConversationService);

  async sendMessage() {
    await this.conversationService.sendMessage({
      conversationId: 'conv-123',
      type: 'text',
      payload: { text: 'Hello!' }
    });
  }

  async createConversation() {
    const conv = await this.conversationService.createConversation(
      ['user-1', 'user-2'],
      'private'
    );
  }
}
```

## 🧪 Testing

```typescript
import { TestBed } from '@angular/core/testing';
import { provideConversation, AXConversationService } from '@acorex/components/conversation';
import { MockUserApi, MockConversationApi, MockMessageApi } from './mocks/mock-apis';

describe('MyComponent', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        provideConversation({
          userApi: MockUserApi,
          conversationApi: MockConversationApi,
          messageApi: MockMessageApi,
        }),
      ],
    });
  });

  it('should send message', async () => {
    const service = TestBed.inject(AXConversationService);
    const message = await service.sendMessage({
      conversationId: 'test',
      type: 'text',
      payload: { text: 'Test' },
    });
    expect(message).toBeDefined();
  });
});
```

## 🎯 Message Types

Supported message types out of the box:

- **text** - Plain text messages
- **image** - Image messages with thumbnails
- **video** - Video messages with playback
- **audio** - Audio file messages
- **voice** - Voice recordings
- **file** - Generic file attachments
- **location** - Location sharing
- **sticker** - Sticker messages
- **contact** - Contact card sharing
- **system** - System notifications

## 🔒 Security Considerations

- **API Keys**: Never hardcode API keys in source code. Use environment variables or injection tokens.
- **File Upload**: Validate file types and sizes on both client and server.
- **XSS Protection**: All user content is sanitized by default.
- **Authentication**: Implement proper authentication in your API layer.

## 📊 Performance Tips

1. **Virtual Scrolling**: Enabled by default for large message lists
2. **Lazy Loading**: Images and media are loaded on demand
3. **Pagination**: Messages are loaded in pages to reduce initial load
4. **Debouncing**: Typing indicators are debounced to reduce network traffic
5. **Memoization**: Use computed signals for expensive calculations

## 🐛 Troubleshooting

### Common Issues

**Issue**: Messages not appearing

- Check if API is connected: `conversationService.connectionStatus$()`
- Verify API implementation returns correct data structure

**Issue**: File upload fails

- Check composer file-type catalogs and per-action `uploadConstraints` (`allowedMimeTypes`, `minSize`, `maxSize`)
- Register a handler service subscribed to `AXUploaderService.onUpload` (and resolve/delete events) with progress and `AbortSignal` support

**Issue**: Styling issues

- Ensure all Acorex component styles are imported
- Check for CSS conflicts with global styles

## 📚 Additional Resources

- [Quick Start Guide](./docs/QUICK-START.md) - Get started in 5 minutes
- [Architecture Overview](./docs/ARCHITECTURE-OVERVIEW.md) - Understand the module structure
- [API Documentation](./docs/ARCHITECTURE-APIS.md) - Implement custom backends
- [Component Guide](./docs/ARCHITECTURE-COMPONENTS.md) - Learn about components
- [Plugin System](./docs/ARCHITECTURE-PLUGINS.md) - Extend functionality
- [Usage Guide](./docs/USAGE-GUIDE.md) - Advanced usage patterns

## 🤝 Contributing

Contributions are welcome! Please read our [Contributing Guide](./CONTRIBUTING.md) for details.

## 📄 License

MIT License - see LICENSE file for details

## 🔄 Changelog

See [CHANGELOG.md](./CHANGELOG.md) for version history and updates.

## 💬 Support

- GitHub Issues: [Report a bug](https://github.com/acorexui/acorex-ui/issues)
- Discussions: [Ask questions](https://github.com/acorexui/acorex-ui/discussions)
