Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ celerybeat-schedule
.spyderproject
.spyproject

# vscode project settings
.vscode

# Rope project settings
.ropeproject

Expand Down
6 changes: 3 additions & 3 deletions packages/jupyter-chat/src/components/attachments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

import CloseIcon from '@mui/icons-material/Close';
import { Box, Button, Tooltip } from '@mui/material';
import React, { useContext } from 'react';
import React from 'react';
import { PathExt } from '@jupyterlab/coreutils';
import { UUID } from '@lumino/coreutils';

import { useChatContext } from '../context';
import { IAttachment } from '../types';
import { AttachmentOpenerContext } from '../context';

const ATTACHMENT_CLASS = 'jp-chat-attachment';
const ATTACHMENT_CLICKABLE_CLASS = 'jp-chat-attachment-clickable';
Expand Down Expand Up @@ -87,7 +87,7 @@ export type AttachmentProps = AttachmentsProps & {
*/
export function AttachmentPreview(props: AttachmentProps): JSX.Element {
const remove_tooltip = 'Remove attachment';
const attachmentOpenerRegistry = useContext(AttachmentOpenerContext);
const { attachmentOpenerRegistry } = useChatContext();
const isClickable = !!attachmentOpenerRegistry?.get(props.attachment.type);

return (
Expand Down
37 changes: 13 additions & 24 deletions packages/jupyter-chat/src/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from './input';
import { JlThemeProvider } from './jl-theme-provider';
import { ChatMessages } from './messages';
import { AttachmentOpenerContext } from '../context';
import { ChatReactContext } from '../context';
import { IChatModel } from '../model';
import {
IAttachmentOpenerRegistry,
Expand All @@ -27,7 +27,7 @@ import {
} from '../registers';
import { ChatArea } from '../types';

export function ChatBody(props: Chat.IChatBodyProps): JSX.Element {
export function ChatBody(props: Chat.IChatProps): JSX.Element {
const { model } = props;
let { inputToolbarRegistry } = props;
if (!inputToolbarRegistry) {
Expand All @@ -36,17 +36,14 @@ export function ChatBody(props: Chat.IChatBodyProps): JSX.Element {
// const horizontalPadding = props.area === 'main' ? 8 : 4;
const horizontalPadding = 4;

const contextValue: Chat.IChatProps = {
...props,
inputToolbarRegistry
};

return (
<AttachmentOpenerContext.Provider value={props.attachmentOpenerRegistry}>
<ChatMessages
rmRegistry={props.rmRegistry}
model={model}
chatCommandRegistry={props.chatCommandRegistry}
inputToolbarRegistry={inputToolbarRegistry}
messageFooterRegistry={props.messageFooterRegistry}
welcomeMessage={props.welcomeMessage}
area={props.area}
/>
<ChatReactContext.Provider value={contextValue}>
<ChatMessages />
<ChatInput
sx={{
paddingLeft: horizontalPadding,
Expand All @@ -55,17 +52,13 @@ export function ChatBody(props: Chat.IChatBodyProps): JSX.Element {
paddingBottom: 0
}}
model={model.input}
chatCommandRegistry={props.chatCommandRegistry}
toolbarRegistry={inputToolbarRegistry}
area={props.area}
chatModel={model}
/>
</AttachmentOpenerContext.Provider>
</ChatReactContext.Provider>
);
}

export function Chat(props: Chat.IOptions): JSX.Element {
const [view, setView] = useState<Chat.View>(props.chatView || Chat.View.chat);
const [view, setView] = useState<Chat.View>(Chat.View.chat);
return (
<JlThemeProvider themeManager={props.themeManager ?? null}>
<Box
Expand Down Expand Up @@ -117,7 +110,7 @@ export namespace Chat {
/**
* The props for the chat body component.
*/
export interface IChatBodyProps {
export interface IChatProps {
/**
* The chat model.
*/
Expand Down Expand Up @@ -155,15 +148,11 @@ export namespace Chat {
/**
* The options to build the Chat UI.
*/
export interface IOptions extends IChatBodyProps {
export interface IOptions extends IChatProps {
/**
* The theme manager.
*/
themeManager?: IThemeManager | null;
/**
* The view to render.
*/
chatView?: View;
/**
* A settings panel that can be used for dedicated settings (e.g. jupyter-ai)
*/
Expand Down
60 changes: 22 additions & 38 deletions packages/jupyter-chat/src/components/input/chat-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,28 @@ import {
import clsx from 'clsx';
import React, { useEffect, useRef, useState } from 'react';

import { InputToolbarRegistry } from './toolbar-registry';
import { useChatCommands } from './use-chat-commands';
import { AttachmentPreviewList } from '../attachments';
import {
IInputToolbarRegistry,
InputToolbarRegistry,
useChatCommands
} from '.';
import { useChatContext } from '../../context';
import { IInputModel, InputModel } from '../../input-model';
import { IChatCommandRegistry } from '../../registers';
import { IAttachment, ChatArea } from '../../types';
import { IChatModel } from '../../model';
import { InputWritingIndicator } from './writing-indicator';
import { IAttachment } from '../../types';

const INPUT_BOX_CLASS = 'jp-chat-input-container';
const INPUT_TEXTFIELD_CLASS = 'jp-chat-input-textfield';
const INPUT_TOOLBAR_CLASS = 'jp-chat-input-toolbar';

export function ChatInput(props: ChatInput.IProps): JSX.Element {
const { model, toolbarRegistry } = props;
const { model } = props;
const { area, chatCommandRegistry, inputToolbarRegistry } = useChatContext();
const chatModel = useChatContext().model;

const [input, setInput] = useState<string>(model.value);
const inputRef = useRef<HTMLInputElement>();

const chatCommands = useChatCommands(model, props.chatCommandRegistry);
const chatCommands = useChatCommands(model, chatCommandRegistry);

const [sendWithShiftEnter, setSendWithShiftEnter] = useState<boolean>(
model.config.sendWithShiftEnter ?? false
Expand Down Expand Up @@ -99,22 +99,22 @@ export function ChatInput(props: ChatInput.IProps): JSX.Element {
*/
useEffect(() => {
const updateToolbar = () => {
setToolbarElements(toolbarRegistry.getItems());
setToolbarElements(inputToolbarRegistry?.getItems() || []);
};

toolbarRegistry.itemsChanged.connect(updateToolbar);
inputToolbarRegistry?.itemsChanged.connect(updateToolbar);
updateToolbar();

return () => {
toolbarRegistry.itemsChanged.disconnect(updateToolbar);
inputToolbarRegistry?.itemsChanged.disconnect(updateToolbar);
};
}, [toolbarRegistry]);
}, [inputToolbarRegistry]);

/**
* Handle the changes in the writers list.
*/
useEffect(() => {
if (!props.chatModel) {
if (!chatModel) {
return;
}

Expand All @@ -124,15 +124,15 @@ export function ChatInput(props: ChatInput.IProps): JSX.Element {
};

// Set initial writers state
const initialWriters = props.chatModel.writers;
const initialWriters = chatModel.writers;
setWriters(initialWriters);

props.chatModel.writersChanged?.connect(updateWriters);
chatModel.writersChanged?.connect(updateWriters);

return () => {
props.chatModel?.writersChanged?.disconnect(updateWriters);
chatModel?.writersChanged?.disconnect(updateWriters);
};
}, [props.chatModel]);
}, [chatModel]);

const inputExists = !!input.trim();

Expand Down Expand Up @@ -196,14 +196,14 @@ export function ChatInput(props: ChatInput.IProps): JSX.Element {
(!sendWithShiftEnter && !event.shiftKey)
) {
// Run all command providers
await props.chatCommandRegistry?.onSubmit(model);
await chatCommandRegistry?.onSubmit(model);
model.send(model.value);
event.stopPropagation();
event.preventDefault();
}
}

const horizontalPadding = props.area === 'sidebar' ? 1.5 : 2;
const horizontalPadding = area === 'sidebar' ? 1.5 : 2;

return (
<Box
Expand Down Expand Up @@ -333,8 +333,8 @@ export function ChatInput(props: ChatInput.IProps): JSX.Element {
<item.element
key={index}
model={model}
chatCommandRegistry={props.chatCommandRegistry}
chatModel={props.chatModel}
chatCommandRegistry={chatCommandRegistry}
chatModel={chatModel}
edit={props.edit}
/>
))}
Expand All @@ -357,10 +357,6 @@ export namespace ChatInput {
* The input model.
*/
model: IInputModel;
/**
* The toolbar registry.
*/
toolbarRegistry: IInputToolbarRegistry;
/**
* The function to be called to cancel editing.
*/
Expand All @@ -369,18 +365,6 @@ export namespace ChatInput {
* Custom mui/material styles.
*/
sx?: SxProps<Theme>;
/**
* Chat command registry.
*/
chatCommandRegistry?: IChatCommandRegistry;
/**
* The area where the chat is displayed.
*/
area?: ChatArea;
/**
* The chat model.
*/
chatModel?: IChatModel;
/**
* Whether the input is in edit mode (editing an existing message).
* Defaults to false (new message mode).
Expand Down
22 changes: 12 additions & 10 deletions packages/jupyter-chat/src/components/messages/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@
import { Box } from '@mui/material';
import React from 'react';

import {
IMessageFooterRegistry,
MessageFooterSectionProps
} from '../../registers';
import { useChatContext } from '../../context';
import { IChatMessage } from '../../types';

/**
* The chat footer component properties.
*/
export interface IMessageFootersProps extends MessageFooterSectionProps {
export interface IMessageFootersProps {
/**
* The chat footer registry.
* The chat model.
*/
registry: IMessageFooterRegistry;
message: IChatMessage;
}

/**
Expand All @@ -27,9 +25,13 @@ export interface IMessageFootersProps extends MessageFooterSectionProps {
*/
export function MessageFooterComponent(
props: IMessageFootersProps
): JSX.Element {
const { message, model, registry } = props;
const footer = registry.getFooter();
): JSX.Element | null {
const { message } = props;
const { model, messageFooterRegistry } = useChatContext();
if (!messageFooterRegistry) {
return null;
}
const footer = messageFooterRegistry.getFooter();

return (
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
Expand Down
18 changes: 5 additions & 13 deletions packages/jupyter-chat/src/components/messages/message-renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
* Distributed under the terms of the Modified BSD License.
*/

import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
import { PromiseDelegate } from '@lumino/coreutils';
import React, { useState, useEffect } from 'react';
import { createPortal } from 'react-dom';

import { CodeToolbar, CodeToolbarProps } from '../code-blocks/code-toolbar';
import { MessageToolbar } from './toolbar';
import { CodeToolbar, CodeToolbarProps } from '../code-blocks/code-toolbar';
import { useChatContext } from '../../context';
import { MarkdownRenderer, MD_RENDERED_CLASS } from '../../markdown-renderer';
import { IChatModel } from '../../model';

/**
* The type of the props for the MessageRenderer component.
Expand All @@ -21,14 +20,6 @@ type MessageRendererProps = {
* The string to render.
*/
markdownStr: string;
/**
* The rendermime registry.
*/
rmRegistry: IRenderMimeRegistry;
/**
* The model of the chat.
*/
model: IChatModel;
/**
* The promise to resolve when the message is rendered.
*/
Expand All @@ -51,7 +42,8 @@ type MessageRendererProps = {
* The message renderer base component.
*/
function MessageRendererBase(props: MessageRendererProps): JSX.Element {
const { markdownStr, rmRegistry } = props;
const { markdownStr } = props;
const { model, rmRegistry } = useChatContext();
const appendContent = props.appendContent || false;
const [renderedContent, setRenderedContent] = useState<HTMLElement | null>(
null
Expand Down Expand Up @@ -81,7 +73,7 @@ function MessageRendererBase(props: MessageRendererProps): JSX.Element {
);
newCodeToolbarDefns.push([
codeToolbarRoot,
{ model: props.model, content: preBlock.textContent || '' }
{ model: model, content: preBlock.textContent || '' }
]);
});

Expand Down
Loading
Loading