wip: snapshot das alterações não commitadas (2026-10-20)

Origem: D:/Documents/Github/LocalAiApp
Arquivos omitidos (segredos, bancos de dados, logs, >50 MB): 0
This commit is contained in:
evandro committed 2026-10-20 00:48:09 -03:00
1 parent ac215b4229
commit e08189f640
17 files changed
+2914 -13236

No files matched your search

+24 -7
View File
@@ -26,6 +26,17 @@ export default function ChatScreen() {
const editMessage = useAppStore(state => state.editMessage);
const { sendMessage, stopStreaming, regenerateResponse, isStreaming, isConnected } = useLMStudio();
const flatListRef = useRef<FlatList>(null);
const isUserScrollingRef = useRef(false);
const isAutoScrollEnabled = useRef(true);
const prevMessagesLength = useRef(messages.length);
const handleScroll = useCallback((event: any) => {
const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent;
// if user is within 100 pixels of the bottom, it's considered at the bottom
const paddingToBottom = 100;
const isCloseToBottom = layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom;
isAutoScrollEnabled.current = isCloseToBottom;
}, []);
// Find the editing message content
const editingMessage = editingMessageId
@@ -69,6 +80,7 @@ export default function ChatScreen() {
}, 100);
} else {
sendMessage(text);
isAutoScrollEnabled.current = true; // explicitly re-enable on manual send
}
}, [editingMessageId, editingMessage, editMessage, deleteMessagesAfter, setEditingMessageId, sendMessage]);
@@ -81,17 +93,19 @@ export default function ChatScreen() {
: null;
useEffect(() => {
const isNewMessage = messages.length > prevMessagesLength.current;
prevMessagesLength.current = messages.length;
if (messages.length > 0 && flatListRef.current) {
setTimeout(() => {
flatListRef.current?.scrollToEnd({ animated: !isStreaming });
if ((isAutoScrollEnabled.current && !isUserScrollingRef.current) || isNewMessage) {
flatListRef.current?.scrollToEnd({ animated: true });
}
}, 100);
}
}, [messages.length, messages[messages.length - 1]?.content?.length, isStreaming]);
}, [messages.length, messages[messages.length - 1]?.content?.length]);
const showTypingIndicator = isStreaming &&
messages.length > 0 &&
messages[messages.length - 1]?.role === 'assistant' &&
messages[messages.length - 1]?.content === '';
return (
<KeyboardAvoidingView
@@ -137,6 +151,10 @@ export default function ChatScreen() {
ref={flatListRef}
data={messages}
keyExtractor={(item) => item.id}
onScroll={handleScroll}
onScrollBeginDrag={() => isUserScrollingRef.current = true}
onScrollEndDrag={() => isUserScrollingRef.current = false}
scrollEventThrottle={16}
renderItem={({ item, index }) => (
<Animated.View entering={FadeInDown.duration(300).delay(index > messages.length - 4 ? 100 : 0)}>
<MessageBubble
@@ -151,7 +169,6 @@ export default function ChatScreen() {
)}
contentContainerStyle={styles.listContent}
/>
{showTypingIndicator && <TypingIndicator />}
</>
)}