Skip to content

Commit

Permalink
refactor: Message to ChatMessage type
Browse files Browse the repository at this point in the history
  • Loading branch information
getnashty committed Nov 28, 2024
1 parent baf4538 commit ca30827
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 99 deletions.
4 changes: 2 additions & 2 deletions src/modules/AieraChat/Header/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { MicroSearch } from '@aiera/client-sdk/components/Svg/MicroSearch';
import { VirtuosoMessageListMethods } from '@virtuoso.dev/message-list';
import classNames from 'classnames';
import React, { ChangeEvent, KeyboardEvent, RefObject, useCallback, useEffect, useState } from 'react';
import { Message } from '../../services/messages';
import { useChatStore } from '../../store';
import { IconButton } from '../../IconButton';
import { ChatMessage } from '../../services/messages';

export function Search({ virtuosoRef }: { virtuosoRef: RefObject<VirtuosoMessageListMethods<Message>> }) {
export function Search({ virtuosoRef }: { virtuosoRef: RefObject<VirtuosoMessageListMethods<ChatMessage>> }) {
const { chatId, searchTerm, onSetSearchTerm } = useChatStore();
const { chatTitle, onSetTitle } = useChatStore();
const [showSearch, setShowSearch] = useState(false);
Expand Down
4 changes: 2 additions & 2 deletions src/modules/AieraChat/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { MicroBars } from '@aiera/client-sdk/components/Svg/MicroBars';
import React, { RefObject } from 'react';
import { Search } from './Search';
import { VirtuosoMessageListMethods } from '@virtuoso.dev/message-list';
import { Message } from '../services/messages';
import { IconButton } from '../IconButton';
import { ChatMessage } from '../services/messages';

export function Header({
onOpenMenu,
virtuosoRef,
}: {
virtuosoRef: RefObject<VirtuosoMessageListMethods<Message>>;
virtuosoRef: RefObject<VirtuosoMessageListMethods<ChatMessage>>;
onOpenMenu: () => void;
}) {
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { MicroQuestionMark } from '@aiera/client-sdk/components/Svg/MicroQuestionMark';
import classNames from 'classnames';
import React from 'react';
import { useChatStore } from '../../../store';
import { ChatMessage } from '../../../services/messages';

export const MessagePrompt = ({
data,
className,
isStickyHeader,
}: {
data: ChatMessage;
className?: string;
isStickyHeader?: boolean;
}) => {
const { searchTerm } = useChatStore();
const prompt = data.prompt;
if (!prompt) return null;
return (
<div
className={classNames(
'px-4 bg-slate-200/60-solid rounded-xl flex relative',
{
'py-3.5 min-h-14': !isStickyHeader,
'h-14': isStickyHeader,
},
className
)}
>
<div
className={classNames(
'h-7 self-start flex-shrink-0 w-7 mr-2.5 bg-indigo-600',
'flex items-center justify-center rounded-lg',
{
'mt-3.5': isStickyHeader,
}
)}
>
<MicroQuestionMark className="w-4 text-white" />
</div>
<div className="self-center">
<p
className={classNames('text-base font-bold antialiased leading-[1.125rem]', {
'line-clamp-2': isStickyHeader,
})}
>
{searchTerm
? prompt
.split(new RegExp(`(${searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'))
.map((part, index) =>
part.toLowerCase() === searchTerm.toLowerCase() ? (
<mark key={index} className="bg-yellow-400">
{part}
</mark>
) : (
part
)
)
: prompt}
</p>
</div>
</div>
);
};
75 changes: 8 additions & 67 deletions src/modules/AieraChat/Messages/MessageFactory/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Button } from '@aiera/client-sdk/components/Button';
import { MicroCheck } from '@aiera/client-sdk/components/Svg/MicroCheck';
import { MicroCopy } from '@aiera/client-sdk/components/Svg/MicroCopy';
import { MicroQuestionMark } from '@aiera/client-sdk/components/Svg/MicroQuestionMark';
import { MicroFolder } from '@aiera/client-sdk/components/Svg/MicroFolder';
import { MicroRefresh } from '@aiera/client-sdk/components/Svg/MicroRefresh';
import { MicroSparkles } from '@aiera/client-sdk/components/Svg/MicroSparkles';
import { MicroThumbDown } from '@aiera/client-sdk/components/Svg/MicroThumbDown';
Expand All @@ -14,72 +14,13 @@ import { match } from 'ts-pattern';
import { MessageListContext } from '..';
import { AddSourceDialog } from '../../AddSourceDialog';
import { IconButton } from '../../IconButton';
import { Message } from '../../services/messages';
import { Source, useChatStore } from '../../store';
import { MicroFolder } from '@aiera/client-sdk/components/Svg/MicroFolder';

export const MessagePrompt = ({
data,
className,
isStickyHeader,
}: {
data: Message;
className?: string;
isStickyHeader?: boolean;
}) => {
const { searchTerm } = useChatStore();
const prompt = data.prompt;
if (!prompt) return null;
return (
<div
className={classNames(
'px-4 bg-slate-200/60-solid rounded-xl flex relative',
{
'py-3.5 min-h-14': !isStickyHeader,
'h-14': isStickyHeader,
},
className
)}
>
<div
className={classNames(
'h-7 self-start flex-shrink-0 w-7 mr-2.5 bg-indigo-600',
'flex items-center justify-center rounded-lg',
{
'mt-3.5': isStickyHeader,
}
)}
>
<MicroQuestionMark className="w-4 text-white" />
</div>
<div className="self-center">
<p
className={classNames('text-base font-bold antialiased leading-[1.125rem]', {
'line-clamp-2': isStickyHeader,
})}
>
{searchTerm
? prompt
.split(new RegExp(`(${searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'))
.map((part, index) =>
part.toLowerCase() === searchTerm.toLowerCase() ? (
<mark key={index} className="bg-yellow-400">
{part}
</mark>
) : (
part
)
)
: prompt}
</p>
</div>
</div>
);
};
import { MessagePrompt } from './MessagePrompt';
import { ChatMessage } from '../../services/messages';

type MessageFeedback = 'pos' | 'neg' | undefined;

const ItemContent = ({ data, onReRun }: { onReRun: (k: string) => void; data: Message }) => {
const ItemContent = ({ data, onReRun }: { onReRun: (k: string) => void; data: ChatMessage }) => {
const { onSelectSource, searchTerm } = useChatStore();
const [copied, setCopied] = useState(false);
// TODO getMessage from network / cache for managing feedback
Expand Down Expand Up @@ -216,11 +157,11 @@ const ItemContent = ({ data, onReRun }: { onReRun: (k: string) => void; data: Me
Icon={MicroFolder}
onClick={() => setShowSourceDialog(true)}
>
{localSources.length}
{localSources.length || ''}
</IconButton>
<IconButton
className="ml-2"
hintText="Re-run Response"
hintText="Retry Response"
hintAnchor="top-right"
hintGrow="up-left"
Icon={MicroRefresh}
Expand All @@ -240,7 +181,7 @@ const ItemContent = ({ data, onReRun }: { onReRun: (k: string) => void; data: Me
);
};

const SourcesResponse = ({ data, onConfirm }: { onConfirm: (k: string) => void; data: Message }) => {
const SourcesResponse = ({ data, onConfirm }: { onConfirm: (k: string) => void; data: ChatMessage }) => {
const { onSelectSource, onAddSource } = useChatStore();
const [showSourceDialog, setShowSourceDialog] = useState(false);
const [localSources, setLocalSources] = useState<Source[]>([
Expand Down Expand Up @@ -354,7 +295,7 @@ const SourcesResponse = ({ data, onConfirm }: { onConfirm: (k: string) => void;
);
};

export const MessageFactory: VirtuosoMessageListProps<Message, MessageListContext>['ItemContent'] = ({
export const MessageFactory: VirtuosoMessageListProps<ChatMessage, MessageListContext>['ItemContent'] = ({
data,
context,
}) => {
Expand Down
4 changes: 2 additions & 2 deletions src/modules/AieraChat/Messages/SuggestedPrompts/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { useCallback, useState } from 'react';
import { VirtuosoMessageListProps } from '@virtuoso.dev/message-list';
import { Message } from '../../services/messages';
import { useSuggestedPrompts } from '../../services/suggestedPrompts';
import { LoadingSpinner } from '@aiera/client-sdk/components/LoadingSpinner';
import { Chevron } from '@aiera/client-sdk/components/Svg/Chevron';
import { MessageListContext } from '..';
import { ChatMessage } from '../../services/messages';

export const SuggestedPrompts: VirtuosoMessageListProps<Message, MessageListContext>['EmptyPlaceholder'] = ({
export const SuggestedPrompts: VirtuosoMessageListProps<ChatMessage, MessageListContext>['EmptyPlaceholder'] = ({
context,
}: {
context: MessageListContext;
Expand Down
27 changes: 14 additions & 13 deletions src/modules/AieraChat/Messages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ import {
import classNames from 'classnames';
import React, { Fragment, RefObject, useCallback, useEffect, useMemo } from 'react';
import { Prompt } from '../Prompt';
import { Message, MessageStatus, useChatMessages } from '../services/messages';
import { ChatMessage, ChatMessageStatus, useChatMessages } from '../services/messages';
import { useChatStore } from '../store';
import { MessageFactory, MessagePrompt } from './MessageFactory';
import { MessageFactory } from './MessageFactory';
import './styles.css';
import { SuggestedPrompts } from './SuggestedPrompts';
import { MessagePrompt } from './MessageFactory/MessagePrompt';

let idCounter = 0;

function randomMessage(user: Message['user'], prompt: Message['prompt']): Message {
function randomMessage(user: ChatMessage['user'], prompt: ChatMessage['prompt']): ChatMessage {
return { user, key: `${idCounter++}`, type: 'response', text: 'some other message', prompt, status: 'thinking' };
}

Expand All @@ -28,8 +29,8 @@ export interface MessageListContext {
onConfirm: (k: string) => void;
}

const StickyHeader: VirtuosoMessageListProps<Message, MessageListContext>['StickyHeader'] = () => {
const data: Message[] = useCurrentlyRenderedData();
const StickyHeader: VirtuosoMessageListProps<ChatMessage, MessageListContext>['StickyHeader'] = () => {
const data: ChatMessage[] = useCurrentlyRenderedData();
const { getScrollLocation } = useVirtuosoMethods();
const { listOffset } = getScrollLocation();
const firstPrompt = data[0];
Expand All @@ -56,7 +57,7 @@ export function Messages({
onOpenSources,
virtuosoRef,
}: {
virtuosoRef: RefObject<VirtuosoMessageListMethods<Message>>;
virtuosoRef: RefObject<VirtuosoMessageListMethods<ChatMessage>>;
onOpenSources: () => void;
}) {
const { chatId, sources } = useChatStore();
Expand All @@ -77,7 +78,7 @@ export function Messages({
let counter = 0;
let newMessage = '';
const interval = setInterval(() => {
let status: MessageStatus = 'thinking';
let status: ChatMessageStatus = 'thinking';
if (counter++ > 80) {
clearInterval(interval);
status = 'finished';
Expand Down Expand Up @@ -126,7 +127,7 @@ export function Messages({
setTimeout(() => {
let counter = 0;
const interval = setInterval(() => {
let status: MessageStatus = 'updating';
let status: ChatMessageStatus = 'updating';
if (counter++ > 80) {
clearInterval(interval);
status = 'finished';
Expand All @@ -153,7 +154,7 @@ export function Messages({

const onSubmit = useCallback(
(prompt: string) => {
const myMessage: Message = {
const myMessage: ChatMessage = {
user: 'me',
key: `${idCounter++}`,
text: prompt,
Expand All @@ -171,7 +172,7 @@ export function Messages({

if (sources.length === 0) {
const newKey = `${idCounter++}`;
const sourceMessage: Message = {
const sourceMessage: ChatMessage = {
user: 'other',
key: newKey,
text: 'sourcess',
Expand Down Expand Up @@ -204,7 +205,7 @@ export function Messages({
setTimeout(() => {
let counter = 0;
const interval = setInterval(() => {
let status: MessageStatus = 'updating';
let status: ChatMessageStatus = 'updating';
if (counter++ > 80) {
clearInterval(interval);
status = 'finished';
Expand Down Expand Up @@ -251,11 +252,11 @@ export function Messages({
</div>
) : (
<VirtuosoMessageListLicense licenseKey="">
<VirtuosoMessageList<Message, MessageListContext>
<VirtuosoMessageList<ChatMessage, MessageListContext>
key={chatId || 'new'}
ref={virtuosoRef}
style={{ flex: 1 }}
computeItemKey={({ data }: { data: Message }) => data.key}
computeItemKey={({ data }: { data: ChatMessage }) => data.key}
className="px-4 messagesScrollBars"
initialLocation={{ index: 'LAST', align: 'end' }}
initialData={messages}
Expand Down
4 changes: 2 additions & 2 deletions src/modules/AieraChat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import { Header } from './Header';
import { Menu } from './Menu';
import { Messages } from './Messages';
import { Sources } from './Sources';
import { Message } from './services/messages';
import { useChatStore } from './store';
import './styles.css';
import { ChatMessage } from './services/messages';

export function AieraChat(): ReactElement {
const [showMenu, setShowMenu] = useState(false);
const [showSources, setShowSources] = useState(false);
const [showConfirm, setShowConfirm] = useState(false);
const { selectedSource, onSelectSource } = useChatStore();
const config = useConfig();
const virtuosoRef = useRef<VirtuosoMessageListMethods<Message>>(null);
const virtuosoRef = useRef<VirtuosoMessageListMethods<ChatMessage>>(null);

const [animateTranscriptExit, setAnimateTranscriptExit] = useState(false);

Expand Down
Loading

0 comments on commit ca30827

Please sign in to comment.