APPCHOBO
SYSTEM BOOTING...
v0.1.bit · firebase build · 富士 ed.
LV14
HP87/100
MP42/80
EXP2,840
1,240 G
앱초보의 모험
◀ 프롬프트 창고
#앱별 실전 패턴 · claude-code

[we_are_tonged] 채팅 시스템 (Firestore subcollection)

통했어요 앱: 매칭된 사용자끼리 1:1 채팅.

#we-are-tonged#messaging#chat#firestore
통했어요 앱: 매칭된 사용자끼리 1:1 채팅. Firestore 스키마: ``` chats/{chatId} - user1Id - user2Id - lastMessageAt - lastMessage chats/{chatId}/messages/{messageId} - senderId - text - createdAt - isRead ``` 구현: ```dart class ChatService { static Future<String> getOrCreateChat(String userId1, String userId2) async { // 기존 채팅방 확인 final snap = await db.collection('chats') .where('user1Id', isEqualTo: userId1) .where('user2Id', isEqualTo: userId2) .get(); if (snap.docs.isNotEmpty) { return snap.docs.first.id; } // 새 채팅방 생성 final chatDoc = await db.collection('chats').add({ 'user1Id': userId1, 'user2Id': userId2, 'createdAt': DateTime.now(), 'lastMessageAt': DateTime.now(), }); return chatDoc.id; } static Future<void> sendMessage({ required String chatId, required String senderId, required String text, }) async { // 메시지 추가 await db .collection('chats') .doc(chatId) .collection('messages') .add({ 'senderId': senderId, 'text': text, 'createdAt': DateTime.now(), 'isRead': false, }); // 채팅방 마지막 메시지 업데이트 await db.collection('chats').doc(chatId).update({ 'lastMessageAt': DateTime.now(), 'lastMessage': text, }); } static Stream<List<ChatMessage>> getMessages(String chatId) { return db .collection('chats') .doc(chatId) .collection('messages') .orderBy('createdAt', descending: true) .snapshots() .map((snap) => snap.docs .map((doc) => ChatMessage.fromDoc(doc)) .toList()); } } ``` UI: ```dart class ChatScreen extends StatefulWidget { final String chatId; const ChatScreen({required this.chatId}); @override State<ChatScreen> createState() => _ChatScreenState(); } class _ChatScreenState extends State<ChatScreen> { late TextEditingController _controller; @override void initState() { super.initState(); _controller = TextEditingController(); } @override Widget build(BuildContext context) { return Column( children: [ Expanded( child: StreamBuilder<List<ChatMessage>>( stream: ChatService.getMessages(widget.chatId), builder: (context, snapshot) { final messages = snapshot.data ?? []; return ListView.builder( reverse: true, itemCount: messages.length, itemBuilder: (context, index) { final msg = messages[index]; return ChatBubble(message: msg); }, ); }, ), ), Padding( padding: EdgeInsets.all(8), child: Row( children: [ Expanded( child: TextField( controller: _controller, decoration: InputDecoration(hintText: '메시지'), ), ), IconButton( icon: Icon(Icons.send), onPressed: () { ChatService.sendMessage( chatId: widget.chatId, senderId: currentUserId, text: _controller.text, ); _controller.clear(); }, ), ], ), ), ], ); } } ``` 구현해줄까?
쓰는 법 — 위 칸에 본인 값을 채우면 아래 프롬프트에 바로 반영돼요. 복사 버튼을 누르면 채워진 그대로 클립보드에 담기니까, claude-code(또는 본인이 쓰는 AI)에 붙여넣기만 하면 됩니다. 변수가 없으면 그냥 복사해서 쓰세요.
▼ SPONSORED ▼
프롬프트 하단 광고