diff --git a/src/data/server/socket.tsx b/src/data/server/socket.tsx index 4015fcc..d9093f6 100644 --- a/src/data/server/socket.tsx +++ b/src/data/server/socket.tsx @@ -1,5 +1,5 @@ import { useStore } from '@/data'; -import { MayaRequest, MayaUpdate, WSUpdate } from '@/data/types'; +import { MayaRequest, MayaUpdate, WSUpdate, ThinkingUpdate } from '@/data/types'; import { client } from '@/data/server/updates'; import { WS_URL, WEB, logger } from '@/data'; import 'react-native-get-random-values'; @@ -23,6 +23,7 @@ class Socket { related: client.handleRelatedUpdate, search: client.handleSearchUpdate, slug: client.handleSlugUpdate, + thinking: client.handleThinkingUpdate, }; } @@ -131,6 +132,14 @@ class Socket { logger.info('sending request: ', message.command); }; + + public setThinkingHandler(handler: (data: ThinkingUpdate) => void) { + this.updateHandlers.thinking = handler; + } + + public removeThinkingHandler() { + this.updateHandlers.thinking = client.handleThinkingUpdate; + } } export const socket = new Socket(); diff --git a/src/data/server/updates.tsx b/src/data/server/updates.tsx index 682cc75..535a747 100644 --- a/src/data/server/updates.tsx +++ b/src/data/server/updates.tsx @@ -18,6 +18,7 @@ import { SearchResult, SlugData, UpdateInfo, + ThinkingUpdate, } from '@/data/types'; class ClientUpdate { @@ -119,6 +120,11 @@ class ClientUpdate { state.clearUser(); } } + + handleThinkingUpdate(data: ThinkingUpdate) { + // Handle thinking state updates + logger.info('thinking update:', data.isThinking); + } } export const client = new ClientUpdate(); diff --git a/src/data/types/types.tsx b/src/data/types/types.tsx index 9006d27..90967bf 100644 --- a/src/data/types/types.tsx +++ b/src/data/types/types.tsx @@ -28,7 +28,8 @@ export type WSUpdate = | "confidence" | "related" | "search" - | "slug"; + | "slug" + | "thinking"; export type SuccessCode = | "success" | "token sent" @@ -282,3 +283,8 @@ export interface UserUpdate { update?: WSUpdate & string; background?: boolean; } +export interface ThinkingUpdate { + isThinking: boolean; + update?: WSUpdate & string; + background?: boolean; +} diff --git a/src/data/utils/config.tsx b/src/data/utils/config.tsx index 2e62338..5d5a2e9 100644 --- a/src/data/utils/config.tsx +++ b/src/data/utils/config.tsx @@ -13,7 +13,7 @@ export const ENV: Environment = 'local'; export let DEV_SCREEN: Screen; // Reset local state & storage on app load -export let RESET_STATE = false; +export let RESET_STATE = true; ////////////////////////////////// diff --git a/src/views/chat/components/message/message.tsx b/src/views/chat/components/message/message.tsx index 95e9931..6160d06 100644 --- a/src/views/chat/components/message/message.tsx +++ b/src/views/chat/components/message/message.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { View, StyleSheet } from 'react-native'; +import { View, StyleSheet, ActivityIndicator, Text } from 'react-native'; import { Message, Confidence, Profile } from '@/data/types'; import { Bubble, @@ -31,6 +31,7 @@ interface MessageProps { position?: 'left' | 'right'; stream?: boolean; info?: boolean; + isThinking?: boolean; } const MessageUI: React.FC = props => { @@ -43,6 +44,7 @@ const MessageUI: React.FC = props => { profiles = [], stream = false, info = false, + isThinking = true, position = 'left', } = props; @@ -161,6 +163,18 @@ const MessageUI: React.FC = props => { ); }; + const renderThinkingIndicator = () => { + if (isThinking) { + return ( + + + Thinking... + + ); + } + return null; + }; + return ( = props => { /> {position === 'right' && renderAvatar()} + {renderThinkingIndicator()} {renderButtons()} ); @@ -239,6 +254,16 @@ const getStyles = () => ({ thumbsUp: { paddingBottom: 2, }, + thinkingContainer: { + flexDirection: 'row', + alignItems: 'center', + marginLeft: 62, + marginTop: 8, + }, + thinkingText: { + marginLeft: 8, + color: '#666', + }, }), left: StyleSheet.create({ container: { diff --git a/src/views/chat/components/messages.tsx b/src/views/chat/components/messages.tsx index 4fef5bb..fe5deb5 100644 --- a/src/views/chat/components/messages.tsx +++ b/src/views/chat/components/messages.tsx @@ -10,6 +10,7 @@ interface MessageListProps { style?: ViewStyle; info?: boolean; chatid: string; + isThinking?: boolean; } const MessageList = forwardRef, MessageListProps>( @@ -49,6 +50,7 @@ const MessageList = forwardRef, MessageListProps>( username={usernames[current.sender] || ''} profiles={profiles} info={info} + isThinking={props.isThinking} /> ); } diff --git a/src/views/chat/screens/discussion.tsx b/src/views/chat/screens/discussion.tsx index 6c98a8e..0991177 100644 --- a/src/views/chat/screens/discussion.tsx +++ b/src/views/chat/screens/discussion.tsx @@ -6,6 +6,8 @@ import { KeyboardAvoidingView, FlatList, Keyboard, + ActivityIndicator, + Text, } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { StackNavigationProp } from '@react-navigation/stack'; @@ -14,7 +16,8 @@ import { useRoute } from '@react-navigation/native'; import { RootStackParamList } from '@/views/navigator'; import { Theme, useTheme } from '@/ui/theme'; import { IconButton, Words, Divider } from '@/ui/atoms'; -import { Message, Profile } from '@/data/types'; +import { Message, Profile, ThinkingUpdate } from '@/data/types'; +import { socket } from '@/data/server'; import { State, useStore, @@ -195,6 +198,22 @@ const Discussion: React.FC = () => { // Additional logic for handling the selected topic }; + const [isThinking, setIsThinking] = useState(false); + + useEffect(() => { + // Listen for thinking state updates + const handleThinkingUpdate = (update: ThinkingUpdate) => { + setIsThinking(update.isThinking); + }; + + // Subscribe to thinking updates + socket.setThinkingHandler(handleThinkingUpdate); + + return () => { + socket.removeThinkingHandler(); + }; + }, []); + return ( { info chatid={thread} ref={messagesRef} + isThinking={isThinking} /> {!WEB && }