• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

agentic-dev-library / thumbcode / 21118343446

18 Jan 2026 08:45PM UTC coverage: 43.195% (-2.1%) from 45.31%
21118343446

Pull #49

github

web-flow
Merge 61d4fc1fe into 45b34104c
Pull Request #49: feat(chat): implement real-time chat system for human-agent collaboration

181 of 616 branches covered (29.38%)

Branch coverage included in aggregate %.

44 of 174 new or added lines in 7 files covered. (25.29%)

495 of 949 relevant lines covered (52.16%)

1.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/components/chat/ChatThread.tsx
1
/**
2
 * Chat Thread Component
3
 *
4
 * Displays a scrollable list of messages in a chat thread.
5
 * Includes typing indicators and auto-scroll to bottom.
6
 */
7

8
import { selectThreadMessages, selectTypingIndicators, useChatStore } from '@thumbcode/state';
9
import { useCallback, useEffect, useRef } from 'react';
10
import { FlatList, Text, View } from 'react-native';
11
import { ChatService } from '@/services/chat';
12
import { ChatMessage } from './ChatMessage';
13

14
interface ChatThreadProps {
15
  threadId: string;
16
}
17

18
/**
19
 * Typing indicator dot animation placeholder
20
 */
21
function TypingIndicator({ senders }: { senders: string[] }) {
NEW
22
  if (senders.length === 0) return null;
×
23

NEW
24
  const names = senders.map((s) => {
×
NEW
25
    const nameMap: Record<string, string> = {
×
26
      architect: 'Architect',
27
      implementer: 'Implementer',
28
      reviewer: 'Reviewer',
29
      tester: 'Tester',
30
    };
NEW
31
    return nameMap[s] || s;
×
32
  });
33

NEW
34
  const label = names.length === 1 ? `${names[0]} is typing` : `${names.join(', ')} are typing`;
×
35

NEW
36
  return (
×
37
    <View className="flex-row items-center px-4 py-2">
38
      <View className="flex-row mr-2">
39
        <View className="w-2 h-2 bg-neutral-400 rounded-full mr-1" />
40
        <View className="w-2 h-2 bg-neutral-500 rounded-full mr-1" />
41
        <View className="w-2 h-2 bg-neutral-600 rounded-full" />
42
      </View>
43
      <Text className="text-xs text-neutral-400 font-body italic">{label}...</Text>
44
    </View>
45
  );
46
}
47

48
export function ChatThread({ threadId }: ChatThreadProps) {
NEW
49
  const flatListRef = useRef<FlatList>(null);
×
50

51
  // Subscribe to messages and typing indicators
NEW
52
  const messages = useChatStore(selectThreadMessages(threadId));
×
NEW
53
  const typingSenders = useChatStore(selectTypingIndicators(threadId));
×
54

55
  // Handle approval responses
NEW
56
  const handleApprovalResponse = useCallback(
×
57
    (messageId: string, approved: boolean) => {
NEW
58
      ChatService.respondToApproval(threadId, messageId, approved);
×
59
    },
60
    [threadId]
61
  );
62

63
  // Auto-scroll to bottom on new messages
NEW
64
  useEffect(() => {
×
NEW
65
    if (messages.length > 0) {
×
NEW
66
      setTimeout(() => {
×
NEW
67
        flatListRef.current?.scrollToEnd({ animated: true });
×
68
      }, 100);
69
    }
70
  }, [messages.length]);
71

NEW
72
  if (messages.length === 0) {
×
NEW
73
    return (
×
74
      <View className="flex-1 items-center justify-center p-4">
75
        <Text className="font-display text-lg text-neutral-400 text-center mb-2">
76
          Start the conversation
77
        </Text>
78
        <Text className="font-body text-sm text-neutral-500 text-center">
79
          Send a message to begin collaborating with AI agents
80
        </Text>
81
      </View>
82
    );
83
  }
84

NEW
85
  return (
×
86
    <View className="flex-1">
87
      <FlatList
88
        ref={flatListRef}
89
        data={messages}
NEW
90
        keyExtractor={(item) => item.id}
×
91
        renderItem={({ item }) => (
NEW
92
          <ChatMessage message={item} onApprovalResponse={handleApprovalResponse} />
×
93
        )}
94
        contentContainerStyle={{ paddingHorizontal: 12, paddingVertical: 8 }}
95
        showsVerticalScrollIndicator={false}
96
        onContentSizeChange={() => {
NEW
97
          flatListRef.current?.scrollToEnd({ animated: false });
×
98
        }}
99
      />
100
      <TypingIndicator senders={typingSenders} />
101
    </View>
102
  );
103
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc