Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ai chat): Delete Conversation Confirmation Dialog #27149

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
2 changes: 2 additions & 0 deletions components/ai_chat/core/browser/constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ base::span<const webui::LocalizedString> GetLocalizedStrings() {
{"feedbackPremiumNote", IDS_CHAT_UI_FEEDBACK_PREMIUM_NOTE},
{"submitButtonLabel", IDS_CHAT_UI_SUBMIT_BUTTON_LABEL},
{"cancelButtonLabel", IDS_CHAT_UI_CANCEL_BUTTON_LABEL},
{"deleteButtonLabel", IDS_CHAT_UI_DELETE_BUTTON_LABEL},
{"deleteConversationWarning", IDS_CHAT_UI_DELETE_CONVERSATION_WARNING},
{"saveButtonLabel", IDS_CHAT_UI_SAVE_BUTTON_LABEL},
{"editedLabel", IDS_CHAT_UI_EDITED_LABEL},
{"editButtonLabel", IDS_CHAT_UI_EDIT_BUTTON_LABEL},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function ConversationItem(props: ConversationItemProps) {

const handleDelete: EventListener = (e) => {
e.preventDefault()
aiChatContext.service?.deleteConversation(uuid)
aiChatContext.setDeletingConversationId(uuid)
}

const isEditing = aiChatContext.editingConversationId === uuid
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* Copyright (c) 2025 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

import * as React from 'react'
import Button from '@brave/leo/react/button'
import Dialog from '@brave/leo/react/dialog'

// Utils
import { getLocale } from '$web-common/locale'

// Hooks
import { useAIChat } from '../../state/ai_chat_context'

// Styles
import styles from './style.module.scss'

export default function DeleteConversationModal() {
// Context
const aiChatContext = useAIChat()

// Computed
const title = aiChatContext.visibleConversations.find(
(conversation) =>
conversation.uuid === aiChatContext.deletingConversationId
)?.title || getLocale('conversationListUntitled')

return (
<Dialog
fallaciousreasoning marked this conversation as resolved.
Show resolved Hide resolved
isOpen={!!aiChatContext.deletingConversationId}
showClose
onClose={() => aiChatContext.setDeletingConversationId(null)}
className={styles.deleteConversationDialog}
>
<div
slot='title'
className={styles.deleteConversationDialogTitle}
>
{getLocale('menuDeleteConversation')}
</div>
<div className={styles.deleteConversationBody}>
<div className={styles.conversationNameWrapper}>{title}</div>
{getLocale('deleteConversationWarning')}
</div>
<div
slot='actions'
className={styles.deleteConversationActionsRow}
>
<div className={styles.buttonsWrapper}>
<Button
kind='plain-faint'
size='medium'
onClick={() => aiChatContext.setDeletingConversationId(null)}
>
{getLocale('cancelButtonLabel')}
</Button>
<Button
kind='filled'
size='medium'
onClick={() => {
if (aiChatContext.deletingConversationId) {
aiChatContext.service?.deleteConversation(
aiChatContext.deletingConversationId
)
aiChatContext.setDeletingConversationId(null)
}
}}
>
{getLocale('deleteButtonLabel')}
</Button>
</div>
</div>
</Dialog>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) 2025 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at https://mozilla.org/MPL/2.0/.

.conversationNameWrapper {
display: flex;
align-items: flex-start;
justify-content: flex-start;
width: 100%;
padding: var(--leo-spacing-l);
border-radius: var(--leo-radius-m);
border: 1px solid var(--leo-color-divider-subtle);
font: var(--leo-font-heading-h4);
color: var(--leo-color-text-secondary);
}

.deleteConversationDialogTitle {
font: var(--leo-font-heading-h3);
}

.deleteConversationDialog {
--leo-dialog-padding: 24px;
}

.deleteConversationBody {
display: flex;
flex-direction: column;
gap: var(--leo-spacing-xl);
}

.deleteConversationActionsRow {
justify-content: flex-end;
}

.buttonsWrapper {
display: flex;
gap: var(--leo-spacing-m);
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export default function FeatureMenu(props: Props) {
</div>
</div>
</leo-menu-item>
<leo-menu-item onClick={() => aiChatContext.service?.deleteConversation(conversationContext.conversationUuid!)}>
<leo-menu-item onClick={() => aiChatContext.setDeletingConversationId(conversationContext.conversationUuid!)}>
<div className={classnames(
styles.menuItemWithIcon,
styles.menuItemMainItem
Expand Down
2 changes: 2 additions & 0 deletions components/ai_chat/resources/page/components/main/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import LongConversationInfo from '../alerts/long_conversation_info'
import NoticeConversationStorage from '../notices/notice_conversation_storage'
import WarningPremiumDisconnected from '../alerts/warning_premium_disconnected'
import ConversationsList from '../conversations_list'
import DeleteConversationModal from '../delete_conversation_modal'
import FeedbackForm from '../feedback_form'
import { ConversationHeader } from '../header'
import InputBox from '../input_box'
Expand Down Expand Up @@ -343,6 +344,7 @@ function Main() {
/>
</ToolsButtonMenu>
</div>
<DeleteConversationModal />
</main>
)
}
Expand Down
8 changes: 8 additions & 0 deletions components/ai_chat/resources/page/state/ai_chat_context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type AIChatContextInternal = AIChatContextProps & {

editingConversationId: string | null
setEditingConversationId: (uuid: string | null) => void,
deletingConversationId: string | null
Douglashdaniel marked this conversation as resolved.
Show resolved Hide resolved
setDeletingConversationId: (uuid: string | null) => void

showSidebar: boolean,
toggleSidebar: () => void
Expand All @@ -52,6 +54,8 @@ const defaultContext: AIChatContext = {

editingConversationId: null,
setEditingConversationId: () => { },
deletingConversationId: null,
setDeletingConversationId: () => { },

showSidebar: false,
toggleSidebar: () => { },
Expand All @@ -71,6 +75,8 @@ export function AIChatContextProvider(props: React.PropsWithChildren<AIChatConte
const context = useAPIState(api, defaultContext)
const [editingConversationId, setEditingConversationId] =
React.useState<string | null>(null)
const [deletingConversationId, setDeletingConversationId] =
React.useState<string | null>(null)
const isSmall = useIsSmall()
const [showSidebar, setShowSidebar] = React.useState(isSmall)

Expand All @@ -87,6 +93,8 @@ export function AIChatContextProvider(props: React.PropsWithChildren<AIChatConte
service: api.service,
editingConversationId,
setEditingConversationId,
deletingConversationId,
setDeletingConversationId,
showSidebar,
toggleSidebar: () => setShowSidebar(s => !s),
conversationEntriesComponent: props.conversationEntriesComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ type CustomArgs = {
inputText: string
hasConversation: boolean
editingConversationId: string | null
deletingConversationId: string | null
visibleConversationListCount: number
hasSuggestedQuestions: boolean
hasSiteInfo: boolean
Expand Down Expand Up @@ -427,6 +428,7 @@ const args: CustomArgs = {
hasSuggestedQuestions: true,
hasSiteInfo: true,
editingConversationId: null,
deletingConversationId: null,
isFeedbackFormVisible: false,
isStorageNoticeDismissed: false,
canShowPremiumPrompt: false,
Expand Down Expand Up @@ -522,6 +524,7 @@ function StoryContext(props: React.PropsWithChildren<{args: CustomArgs, setArgs:
conversationEntriesComponent: StorybookConversationEntries,
initialized: options.args.initialized,
editingConversationId: options.args.editingConversationId,
deletingConversationId: options.args.deletingConversationId,
visibleConversations,
isStoragePrefEnabled: options.args.isStoragePrefEnabled,
hasAcceptedAgreement: options.args.hasAcceptedAgreement,
Expand All @@ -542,6 +545,7 @@ function StoryContext(props: React.PropsWithChildren<{args: CustomArgs, setArgs:
dismissPremiumPrompt: () => {},
userRefreshPremiumSession: () => {},
setEditingConversationId: (id: string | null) => setArgs({ editingConversationId: id }),
setDeletingConversationId: (id: string | null) => setArgs({ deletingConversationId: id }),
showSidebar: showSidebar,
toggleSidebar: () => setShowSidebar(s => !s)
}
Expand Down
6 changes: 6 additions & 0 deletions components/resources/ai_chat_ui_strings.grdp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,12 @@
<message name="IDS_CHAT_UI_CANCEL_BUTTON_LABEL" desc="Button label to cancel action">
Cancel
</message>
<message name="IDS_CHAT_UI_DELETE_BUTTON_LABEL" desc="Button label to delete conversation">
Delete
</message>
<message name="IDS_CHAT_UI_DELETE_CONVERSATION_WARNING" desc="A warning issued when the user is trying to delete a conversation">
Are you sure you want to delete this conversation? This action cannot be undone.
</message>
<message name="IDS_CHAT_UI_SAVE_BUTTON_LABEL" desc="Button label to save data/form">
Save
</message>
Expand Down
Loading