Build secure, scalable, and feature-rich chat applications with our comprehensive messaging API. From private conversations to public communities, from secure E2EE chats to real-time P2P communication.
allgram Chat provides enterprise-level security, GDPR compliance, and seamless integration with popular platforms. Perfect for businesses, developers, and organizations requiring professional messaging solutions.
E2EE, FIPS 140-2, GDPR compliant
WebSocket, P2P, instant delivery
REST API, SDKs, comprehensive docs
Build robust chat applications with Node.js and Express.js. Our comprehensive API provides real-time messaging, WebSocket support, and enterprise-grade security features. Perfect for building scalable backend services and real-time chat applications.
// allgram Chat Node.js Integration Example
const express = require('express');
const WebSocket = require('ws');
const crypto = require('crypto');
const axios = require('axios');
class allgramChatClient {
constructor(apiKey, baseUrl = 'https://api.allgram.best') {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
this.ws = null;
this.chats = new Map();
}
// Initialize WebSocket connection
async connectWebSocket() {
try {
this.ws = new WebSocket(`wss://api.allgram.best/ws/messages/`);
this.ws.on('open', () => {
console.log('✅ WebSocket connected');
// Authenticate with API key
this.ws.send(JSON.stringify({
type: 'auth',
api_key: this.apiKey
}));
});
this.ws.on('message', (data) => {
this.handleWebSocketMessage(JSON.parse(data));
});
this.ws.on('error', (error) => {
console.error('WebSocket error:', error);
this.reconnect();
});
} catch (error) {
console.error('Failed to connect WebSocket:', error);
}
}
// Create a new chat
async createChat(name, description, participants, isSecure = false) {
try {
const response = await axios.post(`${this.baseUrl}/chats/create`, {
chat_name: name,
chat_description: description,
participants: participants,
is_secure: isSecure,
is_public: false,
is_p2p: false
}, {
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
}
});
if (response.status === 200) {
const chat = response.data;
this.chats.set(chat.chat_id, chat);
console.log(`✅ Chat created: ${chat.chat_name}`);
return chat;
}
} catch (error) {
console.error('Failed to create chat:', error.response?.data || error.message);
throw error;
}
}
// Send encrypted message
async sendEncryptedMessage(chatId, content, symmetricKey) {
try {
// Encrypt content with AES-256-GCM
const encryptedContent = await this.encryptWithAES(content, symmetricKey);
const response = await axios.post(`${this.baseUrl}/messages/create`, {
chat: chatId,
content: [JSON.stringify({
encrypt_data: encryptedContent
})]
}, {
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
}
});
if (response.status === 200) {
console.log('✅ Encrypted message sent');
return response.data;
}
} catch (error) {
console.error('Failed to send encrypted message:', error.response?.data || error.message);
throw error;
}
}
// Handle WebSocket messages
handleWebSocketMessage(message) {
if (message.content.action) {
this.handleSystemEvent(message);
} else if (message.content.text || message.content.media) {
this.handleNewMessage(message);
}
}
// Handle system events
handleSystemEvent(message) {
switch (message.content.action) {
case 'joined chat':
console.log(`👥 User joined chat: ${message.author}`);
break;
case 'deleted chat':
console.log(`🗑️ Chat deleted: ${message.chat}`);
this.chats.delete(message.chat);
break;
case 'started call':
console.log(`📞 Call started in chat: ${message.chat}`);
break;
}
}
// Handle new messages
handleNewMessage(message) {
console.log(`💬 New message from ${message.author}: ${message.content.text}`);
// Update chat messages cache
this.updateChatMessages(message.chat, message);
}
// AES encryption helper
async encryptWithAES(data, key) {
const algorithm = 'aes-256-gcm';
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipher(algorithm, key);
let encrypted = cipher.update(JSON.stringify(data), 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return {
encrypted,
iv: iv.toString('hex'),
authTag: authTag.toString('hex')
};
}
// Reconnection logic
reconnect() {
setTimeout(() => {
console.log('🔄 Attempting to reconnect...');
this.connectWebSocket();
}, 5000);
}
// Update chat messages cache
updateChatMessages(chatId, message) {
if (!this.chats.has(chatId)) return;
const chat = this.chats.get(chatId);
if (!chat.messages) chat.messages = [];
// Check if message already exists
const existingIndex = chat.messages.findIndex(m => m.message_id === message.message_id);
if (existingIndex !== -1) {
chat.messages[existingIndex] = message;
} else {
chat.messages.push(message);
}
this.chats.set(chatId, chat);
}
}
// Usage example
const chatClient = new allgramChatClient('your-api-key-here');
// Initialize connection
chatClient.connectWebSocket();
// Create a secure chat
chatClient.createChat('Team Chat', 'Secure team communication', ['user1', 'user2'], true)
.then(chat => {
console.log('Chat created successfully:', chat);
})
.catch(error => {
console.error('Failed to create chat:', error);
});
Our Node.js integration provides enterprise-grade chat capabilities with minimal setup. Built on proven technologies like Express.js and WebSocket, it offers exceptional performance and reliability for production applications.
Build native iOS chat applications with Swift and SwiftUI. Our iOS SDK provides seamless integration with UIKit and SwiftUI, real-time messaging, and secure E2EE implementation. Perfect for creating professional iOS chat applications with modern design patterns.
// allgram Chat Swift iOS Integration Example
import SwiftUI
import Combine
import CryptoKit
// MARK: - Chat Models
struct Chat: Codable, Identifiable {
let id: String
let name: String
let description: String
let isSecure: Bool
let isP2P: Bool
let participants: [String]
let creationDate: Date
enum CodingKeys: String, CodingKey {
case id = "chat_id"
case name = "chat_name"
case description = "chat_description"
case isSecure = "is_secure"
case isP2P = "is_p2p"
case participants
case creationDate = "creation_datetime"
}
}
struct Message: Codable, Identifiable {
let id: String
let chatId: String
let author: String
let content: MessageContent
let timestamp: Date
let isEncrypted: Bool
enum CodingKeys: String, CodingKey {
case id = "message_id"
case chatId = "chat"
case author
case content
case timestamp = "creation_datetime"
case isEncrypted = "is_secure"
}
}
struct MessageContent: Codable {
let text: String?
let media: [String]?
let poll: String?
let quote: QuoteData?
}
struct QuoteData: Codable {
let messageId: String
let content: String
let author: String
}
// MARK: - Chat Service
class allgramChatService: ObservableObject {
@Published var chats: [Chat] = []
@Published var currentChat: Chat?
@Published var messages: [Message] = []
@Published var isConnected = false
private var webSocket: URLSessionWebSocketTask?
private var cancellables = Set<AnyCancellable>()
private let baseURL = "https://api.allgram.best"
private let apiKey: String
init(apiKey: String) {
self.apiKey = apiKey
setupWebSocket()
}
// MARK: - WebSocket Setup
private func setupWebSocket() {
guard let url = URL(string: "wss://api.allgram.best/ws/messages/") else { return }
let session = URLSession(configuration: .default)
webSocket = session.webSocketTask(with: url)
webSocket?.resume()
// Authenticate
let authMessage = WebSocketMessage(type: "auth", apiKey: apiKey)
sendWebSocketMessage(authMessage)
// Start receiving messages
receiveMessage()
}
// MARK: - Chat Management
func createChat(name: String, description: String, participants: [String], isSecure: Bool = false) async throws -> Chat {
let url = URL(string: "\(baseURL)/chats/create")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let chatData = [
"chat_name": name,
"chat_description": description,
"participants": participants,
"is_secure": isSecure,
"is_public": false,
"is_p2p": false
]
request.httpBody = try JSONSerialization.data(withJSONObject: chatData)
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw ChatError.serverError
}
let chat = try JSONDecoder().decode(Chat.self, from: data)
DispatchQueue.main.async {
self.chats.append(chat)
}
return chat
}
// MARK: - Message Handling
func sendMessage(_ text: String, to chatId: String) async throws {
let url = URL(string: "\(baseURL)/messages/create")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let messageData = [
"chat": chatId,
"content": [text]
]
request.httpBody = try JSONSerialization.data(withJSONObject: messageData)
let (_, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw ChatError.serverError
}
// Message sent successfully
print("✅ Message sent to chat: \(chatId)")
}
// MARK: - WebSocket Communication
private func sendWebSocketMessage(_ message: WebSocketMessage) {
guard let data = try? JSONEncoder().encode(message),
let jsonString = String(data: data, encoding: .utf8) else { return }
let wsMessage = URLSessionWebSocketTask.Message.string(jsonString)
webSocket?.send(wsMessage) { error in
if let error = error {
print("❌ Failed to send WebSocket message: \(error)")
}
}
}
private func receiveMessage() {
webSocket?.receive { [weak self] result in
switch result {
case .success(let message):
self?.handleWebSocketMessage(message)
self?.receiveMessage() // Continue receiving
case .failure(let error):
print("❌ WebSocket receive error: \(error)")
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self?.reconnect()
}
}
}
}
private func handleWebSocketMessage(_ message: URLSessionWebSocketTask.Message) {
switch message {
case .string(let text):
guard let data = text.data(using: .utf8),
let wsMessage = try? JSONDecoder().decode(WebSocketMessage.self, from: data) else { return }
DispatchQueue.main.async {
self.processWebSocketMessage(wsMessage)
}
default:
break
}
}
private func processWebSocketMessage(_ message: WebSocketMessage) {
if let action = message.action {
handleSystemEvent(action, message: message)
} else if message.content?.text != nil || message.content?.media != nil {
handleNewMessage(message)
}
}
private func handleSystemEvent(_ action: String, message: WebSocketMessage) {
switch action {
case "joined chat":
print("👥 User joined chat: \(message.author ?? "Unknown")")
case "deleted chat":
print("🗑️ Chat deleted: \(message.chat ?? "Unknown")")
if let chatId = message.chat {
removeChat(withId: chatId)
}
case "started call":
print("📞 Call started in chat: \(message.chat ?? "Unknown")")
default:
break
}
}
private func handleNewMessage(_ message: WebSocketMessage) {
guard let chatId = message.chat,
let author = message.author,
let content = message.content else { return }
let newMessage = Message(
id: message.messageId ?? UUID().uuidString,
chatId: chatId,
author: author,
content: content,
timestamp: Date(),
isEncrypted: false
)
DispatchQueue.main.async {
if self.currentChat?.id == chatId {
self.messages.append(newMessage)
}
}
}
// MARK: - Utility Methods
private func removeChat(withId chatId: String) {
DispatchQueue.main.async {
self.chats.removeAll { $0.id == chatId }
if self.currentChat?.id == chatId {
self.currentChat = nil
self.messages = []
}
}
}
private func reconnect() {
print("🔄 Attempting to reconnect...")
setupWebSocket()
}
}
// MARK: - WebSocket Message Model
struct WebSocketMessage: Codable {
let type: String?
let apiKey: String?
let chat: String?
let messageId: String?
let content: MessageContent?
let author: String?
let action: String?
enum CodingKeys: String, CodingKey {
case type
case apiKey = "api_key"
case chat
case messageId = "message_id"
case content
case author
case action
}
}
// MARK: - Error Handling
enum ChatError: Error, LocalizedError {
case serverError
case networkError
case authenticationError
var errorDescription: String? {
switch self {
case .serverError:
return "Server error occurred"
case .networkError:
return "Network connection failed"
case .authenticationError:
return "Authentication failed"
}
}
}
// MARK: - SwiftUI Views
struct ChatListView: View {
@StateObject private var chatService = allgramChatService(apiKey: "your-api-key")
var body: some View {
NavigationView {
List(chatService.chats) { chat in
NavigationLink(destination: ChatDetailView(chat: chat, chatService: chatService)) {
ChatRowView(chat: chat)
}
}
.navigationTitle("Chats")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("New Chat") {
// Show new chat creation
}
}
}
}
}
}
struct ChatRowView: View {
let chat: Chat
var body: some View {
VStack(alignment: .leading, spacing: 4) {
HStack {
Text(chat.name)
.font(.headline)
Spacer()
if chat.isSecure {
Image(systemName: "lock.fill")
.foregroundColor(.green)
}
}
Text(chat.description)
.font(.subheadline)
.foregroundColor(.secondary)
Text("\(chat.participants.size) participants")
.font(.caption)
.foregroundColor(.secondary)
}
.padding(.vertical, 4)
}
}
Our Swift SDK leverages the latest iOS technologies including SwiftUI, Combine, and async/await. Built with modern iOS development patterns, it provides a seamless developer experience while maintaining high performance and security standards.
Build powerful Android chat applications with Kotlin and Jetpack Compose. Our Android SDK provides seamless integration with modern Android development tools, real-time messaging, and P2P chat capabilities. Perfect for creating professional Android chat applications.
// allgram Chat Kotlin Android Integration Example
package com.allgram.chat
import android.util.Log
import androidx.compose.runtime.*
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import java.security.MessageDigest
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec
// MARK: - Data Models
data class Chat(
val chatId: String,
val chatName: String,
val chatDescription: String,
val isSecure: Boolean,
val isP2P: Boolean,
val participants: List<String>,
val creationDatetime: Long,
val isPublic: Boolean = false
)
data class Message(
val messageId: String,
val chatId: String,
val author: String,
val authorAvatar: String,
val content: MessageContent,
val creationDatetime: Long,
val isEncrypted: Boolean = false,
val isRead: Boolean = false
)
data class MessageContent(
val text: String? = null,
val media: List<String>? = null,
val poll: String? = null,
val quote: QuoteData? = null
)
data class QuoteData(
val messageId: String,
val content: String,
val author: String
)
// MARK: - Chat Service
class allgramChatService(
private val apiKey: String,
private val baseUrl: String = "https://api.allgram.best"
) {
private val client = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build()
private var webSocket: WebSocket? = null
private val messageCallbacks = mutableListOf<(Message) -> Unit>()
private val systemEventCallbacks = mutableListOf<(String, String) -> Unit>()
// MARK: - WebSocket Management
fun connectWebSocket() {
val request = Request.Builder()
.url("wss://api.allgram.best/ws/messages/")
.build()
webSocket = client.newWebSocket(request, object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
Log.d("allgramChat", "✅ WebSocket connected")
// Authenticate
sendWebSocketMessage(JSONObject().apply {
put("type", "auth")
put("api_key", apiKey)
}.toString())
}
override fun onMessage(webSocket: WebSocket, text: String) {
try {
val json = JSONObject(text)
handleWebSocketMessage(json)
} catch (e: Exception) {
Log.e("allgramChat", "Failed to parse WebSocket message", e)
}
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
Log.e("allgramChat", "WebSocket failure", t)
// Attempt reconnection
CoroutineScope(Dispatchers.IO).launch {
delay(5000)
connectWebSocket()
}
}
})
}
// MARK: - Chat Management
suspend fun createChat(
name: String,
description: String,
participants: List<String>,
isSecure: Boolean = false,
isP2P: Boolean = false
): Result<Chat> = withContext(Dispatchers.IO) {
try {
val requestBody = JSONObject().apply {
put("chat_name", name)
put("chat_description", description)
put("participants", JSONObject().apply {
participants.forEachIndexed { index, participant ->
put(index.toString(), participant)
}
})
put("is_secure", isSecure)
put("is_public", false)
put("is_p2p", isP2P)
}.toString()
val request = Request.Builder()
.url("$baseUrl/chats/create")
.post(requestBody.toRequestBody("application/json".toMediaType()))
.addHeader("Authorization", "Bearer $apiKey")
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
val responseBody = response.body?.string()
val chatJson = JSONObject(responseBody ?: "")
val chat = Chat(
chatId = chatJson.getString("chat_id"),
chatName = chatJson.getString("chat_name"),
chatDescription = chatJson.getString("chat_description"),
isSecure = chatJson.optBoolean("is_secure", false),
isP2P = chatJson.optBoolean("is_p2p", false),
participants = participants,
creationDatetime = chatJson.optLong("creation_datetime", System.currentTimeMillis() / 1000)
)
Log.d("allgramChat", "✅ Chat created: ${chat.chatName}")
Result.success(chat)
} else {
Log.e("allgramChat", "Failed to create chat: ${response.code}")
Result.failure(Exception("Server error: ${response.code}"))
}
} catch (e: Exception) {
Log.e("allgramChat", "Exception creating chat", e)
Result.failure(e)
}
}
// MARK: - Message Handling
suspend fun sendMessage(
chatId: String,
content: String,
isEncrypted: Boolean = false,
symmetricKey: ByteArray? = null
): Result<Unit> = withContext(Dispatchers.IO) {
try {
val messageContent = if (isEncrypted && symmetricKey != null) {
val encryptedContent = encryptWithAES(content, symmetricKey)
JSONObject().apply {
put("encrypt_data", encryptedContent)
}.toString()
} else {
content
}
val requestBody = JSONObject().apply {
put("chat", chatId)
put("content", JSONObject().apply {
put("0", messageContent)
})
}.toString()
val request = Request.Builder()
.url("$baseUrl/messages/create")
.post(requestBody.toRequestBody("application/json".toMediaType()))
.addHeader("Authorization", "Bearer $apiKey")
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
Log.d("allgramChat", "✅ Message sent to chat: $chatId")
Result.success(Unit)
} else {
Log.e("allgramChat", "Failed to send message: ${response.code}")
Result.failure(Exception("Server error: ${response.code}"))
}
} catch (e: Exception) {
Log.e("allgramChat", "Exception sending message", e)
Result.failure(e)
}
}
// MARK: - WebSocket Communication
private fun sendWebSocketMessage(message: String) {
webSocket?.send(message) ?: run {
Log.w("allgramChat", "WebSocket not connected")
}
}
private fun handleWebSocketMessage(json: JSONObject) {
when {
json.has("action") -> {
val action = json.getString("action")
val chatId = json.optString("chat", "")
handleSystemEvent(action, chatId)
}
json.has("content") -> {
val message = parseMessageFromJson(json)
message?.let { handleNewMessage(it) }
}
}
}
private fun handleSystemEvent(action: String, chatId: String) {
Log.d("allgramChat", "System event: $action in chat: $chatId")
systemEventCallbacks.forEach { callback ->
callback(action, chatId)
}
}
private fun handleNewMessage(message: Message) {
Log.d("allgramChat", "New message from ${message.author}: ${message.content.text}")
messageCallbacks.forEach { callback ->
callback(message)
}
}
private fun parseMessageFromJson(json: JSONObject): Message? {
return try {
val content = json.optJSONObject("content")
Message(
messageId = json.optString("message_id", ""),
chatId = json.optString("chat", ""),
author = json.optString("author", ""),
authorAvatar = json.optString("author_avatar", ""),
content = MessageContent(
text = content?.optString("text"),
media = content?.optJSONArray("media")?.let { mediaArray ->
List(mediaArray.length()) { i -> mediaArray.getString(i) }
},
poll = content?.optString("poll"),
quote = content?.optJSONObject("quote")?.let { quoteJson ->
QuoteData(
messageId = quoteJson.optString("message_id", ""),
content = quoteJson.optString("content", ""),
author = quoteJson.optString("author", "")
)
}
),
creationDatetime = json.optLong("creation_datetime", System.currentTimeMillis() / 1000),
isEncrypted = json.optBoolean("is_secure", false)
)
} catch (e: Exception) {
Log.e("allgramChat", "Failed to parse message", e)
null
}
}
// MARK: - Encryption
private fun encryptWithAES(data: String, key: ByteArray): String {
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val secretKey = SecretKeySpec(key, "AES")
val iv = ByteArray(12).apply {
java.security.SecureRandom().nextBytes(this)
}
val gcmSpec = GCMParameterSpec(128, iv)
cipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmSpec)
val encrypted = cipher.doFinal(data.toByteArray())
return android.util.Base64.encodeToString(
iv + encrypted,
android.util.Base64.NO_WRAP
)
}
// MARK: - Callbacks
fun addMessageCallback(callback: (Message) -> Unit) {
messageCallbacks.add(callback)
}
fun addSystemEventCallback(callback: (String, String) -> Unit) {
systemEventCallbacks.add(callback)
}
fun removeMessageCallback(callback: (Message) -> Unit) {
messageCallbacks.remove(callback)
}
fun removeSystemEventCallback(callback: (String, String) -> Unit) {
systemEventCallbacks.remove(callback)
}
// MARK: - Cleanup
fun disconnect() {
webSocket?.close(1000, "Disconnecting")
webSocket = null
}
}
// MARK: - ViewModel
class ChatViewModel(
private val chatService: allgramChatService
) : ViewModel() {
private val _chats = MutableStateFlow<List<Chat>>(emptyList())
val chats: StateFlow<List<Chat>> = _chats.asStateFlow()
private val _currentChat = MutableStateFlow<Chat?>(null)
val currentChat: StateFlow<Chat?> = _currentChat.asStateFlow()
private val _messages = MutableStateFlow<List<Message>>(emptyList())
val messages: StateFlow<List<Message>> = _messages.asStateFlow()
private val _isLoading = MutableStateFlow(false)
val isLoading: StateFlow<Boolean> = _isLoading.asStateFlow()
init {
setupChatService()
}
private fun setupChatService() {
chatService.addMessageCallback { message ->
if (message.chatId == _currentChat.value?.chatId) {
_messages.value = _messages.value + message
}
}
chatService.addSystemEventCallback { action, chatId ->
when (action) {
"deleted chat" -> {
_chats.value = _chats.value.filter { it.chatId != chatId }
if (_currentChat.value?.chatId == chatId) {
_currentChat.value = null
_messages.value = emptyList()
}
}
"joined chat" -> {
// Refresh chat participants
}
}
}
}
fun createChat(name: String, description: String, participants: List<String>, isSecure: Boolean = false) {
viewModelScope.launch {
_isLoading.value = true
try {
val result = chatService.createChat(name, description, participants, isSecure)
result.onSuccess { chat ->
_chats.value = _chats.value + chat
}.onFailure { error ->
Log.e("ChatViewModel", "Failed to create chat", error)
}
} finally {
_isLoading.value = false
}
}
}
fun sendMessage(content: String) {
val currentChat = _currentChat.value ?: return
viewModelScope.launch {
val result = chatService.sendMessage(currentChat.chatId, content)
result.onFailure { error ->
Log.e("ChatViewModel", "Failed to send message", error)
}
}
}
fun selectChat(chat: Chat) {
_currentChat.value = chat
// Load chat messages
loadChatMessages(chat.chatId)
}
private fun loadChatMessages(chatId: String) {
// Implementation for loading chat messages
// This would typically involve API calls to fetch message history
}
override fun onCleared() {
super.onCleared()
chatService.disconnect()
}
}
// MARK: - Compose UI
@Composable
fun ChatListScreen(
viewModel: ChatViewModel = viewModel { ChatViewModel(allgramChatService("your-api-key")) }
) {
val chats by viewModel.chats.collectAsState()
val isLoading by viewModel.isLoading.collectAsState()
LazyColumn {
items(chats) { chat ->
ChatItem(
chat = chat,
onClick = { viewModel.selectChat(chat) }
)
}
}
if (isLoading) {
CircularProgressIndicator()
}
}
@Composable
fun ChatItem(
chat: Chat,
onClick: () -> Unit
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.clickable { onClick() },
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Column(
modifier = Modifier.padding(16.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = chat.chatName,
style = MaterialTheme.typography.h6
)
if (chat.isSecure) {
Icon(
imageVector = Icons.Default.Lock,
contentDescription = "Secure Chat",
tint = Color.Green
)
}
}
Text(
text = chat.chatDescription,
style = MaterialTheme.typography.body2,
color = MaterialTheme.colors.onSurface.copy(alpha = 0.6f)
)
Text(
text = "${chat.participants.size} participants",
style = MaterialTheme.typography.caption,
color = MaterialTheme.colors.onSurface.copy(alpha = 0.6f)
)
}
}
}
Our Kotlin SDK leverages the latest Android technologies including Jetpack Compose, Coroutines, and modern Android architecture patterns. Built with performance and developer experience in mind, it provides a robust foundation for building scalable chat applications.
Ready to take your chat integration to the next level? Explore our comprehensive resources and advanced features to build enterprise-grade chat applications with allgram.
Learn about our enterprise security features, GDPR compliance, and FIPS 140-2 certification.
Learn More →Discover advanced techniques for optimizing chat performance and scalability.
Learn More →Join our developer community for support, updates, and collaboration.
Join Community →