Skip to content

Commit

Permalink
Hide the 'include selection' menu when editing a message or if the to…
Browse files Browse the repository at this point in the history
…ols are not available
  • Loading branch information
brichet committed Sep 17, 2024
1 parent 3be830c commit 20907ce
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 72 deletions.
14 changes: 14 additions & 0 deletions packages/jupyter-chat/src/components/chat-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ export function ChatInput(props: ChatInput.IProps): JSX.Element {
model.config.sendWithShiftEnter ?? false
);

// Display the include selection menu if it is not explicitly hidden, and if at least
// one of the tool to check for text or cell selection is enabled.
let includeSelectionVisible = props.includeSelectionVisible ?? true;
if (model.activeCellManager === null && model.selectionWatcher === null) {
includeSelectionVisible = false;
}

// store reference to the input element to enable focusing it easily
const inputRef = useRef<HTMLInputElement>();

Expand Down Expand Up @@ -140,6 +147,8 @@ export function ChatInput(props: ChatInput.IProps): JSX.Element {

/**
* Triggered when sending the message.
*
* Add code block if cell or text is selected.
*/
function onSend(selection?: Selection) {
let content = input;
Expand Down Expand Up @@ -229,6 +238,7 @@ ${selection.source}
sendWithShiftEnter={sendWithShiftEnter}
inputExists={input.length > 0}
onSend={onSend}
includeSelectionVisible={includeSelectionVisible}
/>
</InputAdornment>
)
Expand Down Expand Up @@ -297,6 +307,10 @@ export namespace ChatInput {
* The function to be called to cancel editing.
*/
onCancel?: () => unknown;
/**
* Whether to allow or not including selection.
*/
includeSelectionVisible?: boolean;
/**
* Custom mui/material styles.
*/
Expand Down
1 change: 1 addition & 0 deletions packages/jupyter-chat/src/components/chat-messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ export function ChatMessage(props: ChatMessageProps): JSX.Element {
onSend={(input: string) => updateMessage(message.id, input)}
onCancel={() => cancelEdition()}
model={model}
includeSelectionVisible={false}
/>
) : (
<RendermimeMarkdown
Expand Down
153 changes: 81 additions & 72 deletions packages/jupyter-chat/src/components/input/send-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ export type SendButtonProps = {
sendWithShiftEnter: boolean;
inputExists: boolean;
onSend: (selection?: Selection) => unknown;
includeSelectionVisible?: boolean;
};

export function SendButton(props: SendButtonProps): JSX.Element {
const { activeCellManager, selectionWatcher } = props.model;
const includeSelectionVisible = props.includeSelectionVisible ?? true;
const [menuAnchorEl, setMenuAnchorEl] = useState<HTMLElement | null>(null);
const [menuOpen, setMenuOpen] = useState(false);

Expand Down Expand Up @@ -58,15 +60,16 @@ export function SendButton(props: SendButtonProps): JSX.Element {
setSelectionTooltip(tooltip);
};

selectionWatcher?.selectionChanged.connect(toggleIncludeState);
activeCellManager?.availabilityChanged.connect(toggleIncludeState);

toggleIncludeState();
if (includeSelectionVisible) {
selectionWatcher?.selectionChanged.connect(toggleIncludeState);
activeCellManager?.availabilityChanged.connect(toggleIncludeState);
toggleIncludeState();
}
return () => {
selectionWatcher?.selectionChanged.disconnect(toggleIncludeState);
activeCellManager?.availabilityChanged.disconnect(toggleIncludeState);
};
}, [selectionWatcher, activeCellManager]);
}, [activeCellManager, selectionWatcher, includeSelectionVisible]);

const defaultTooltip = props.sendWithShiftEnter
? 'Send message (SHIFT+ENTER)'
Expand Down Expand Up @@ -115,73 +118,79 @@ export function SendButton(props: SendButtonProps): JSX.Element {
>
<SendIcon />
</TooltippedButton>
<TooltippedButton
onClick={e => {
openMenu(e.currentTarget);
}}
disabled={disabled}
tooltip=""
buttonProps={{
variant: 'contained',
onKeyDown: e => {
if (e.key !== 'Enter' && e.key !== ' ') {
return;
}
openMenu(e.currentTarget);
// stopping propagation of this event prevents the prompt from being
// sent when the dropdown button is selected and clicked via 'Enter'.
e.stopPropagation();
}
}}
sx={{
minWidth: 'unset',
padding: '4px 0px',
borderRadius: '0px 2px 2px 0px',
borderLeft: '1px solid white'
}}
>
<KeyboardArrowDown />
</TooltippedButton>
<Menu
open={menuOpen}
onClose={closeMenu}
anchorEl={menuAnchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'right'
}}
sx={{
'& .MuiMenuItem-root': {
display: 'flex',
alignItems: 'centincludeSelectionDisableder',
gap: '8px'
},
'& svg': {
lineHeight: 0
}
}}
>
<MenuItem
onClick={e => {
sendWithSelection();
// prevent sending second message with no selection
e.stopPropagation();
}}
disabled={disableInclude}
>
<includeSelectionIcon.react />
<Box>
<Typography display="block">Send message with selection</Typography>
<Typography display="block" sx={{ opacity: 0.618 }}>
{selectionTooltip}
</Typography>
</Box>
</MenuItem>
</Menu>
{includeSelectionVisible && (
<>
<TooltippedButton
onClick={e => {
openMenu(e.currentTarget);
}}
disabled={disabled}
tooltip=""
buttonProps={{
variant: 'contained',
onKeyDown: e => {
if (e.key !== 'Enter' && e.key !== ' ') {
return;
}
openMenu(e.currentTarget);
// stopping propagation of this event prevents the prompt from being
// sent when the dropdown button is selected and clicked via 'Enter'.
e.stopPropagation();
}
}}
sx={{
minWidth: 'unset',
padding: '4px 0px',
borderRadius: '0px 2px 2px 0px',
borderLeft: '1px solid white'
}}
>
<KeyboardArrowDown />
</TooltippedButton>
<Menu
open={menuOpen}
onClose={closeMenu}
anchorEl={menuAnchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'right'
}}
sx={{
'& .MuiMenuItem-root': {
display: 'flex',
alignItems: 'centincludeSelectionDisableder',
gap: '8px'
},
'& svg': {
lineHeight: 0
}
}}
>
<MenuItem
onClick={e => {
sendWithSelection();
// prevent sending second message with no selection
e.stopPropagation();
}}
disabled={disableInclude}
>
<includeSelectionIcon.react />
<Box>
<Typography display="block">
Send message with selection
</Typography>
<Typography display="block" sx={{ opacity: 0.618 }}>
{selectionTooltip}
</Typography>
</Box>
</MenuItem>
</Menu>
</>
)}
</Box>
);
}

0 comments on commit 20907ce

Please sign in to comment.