lobe-chat icon indicating copy to clipboard operation
lobe-chat copied to clipboard

[Request] Option to disable message deletion confirmation

Open Rekkertt opened this issue 1 year ago • 6 comments

🥰 Feature Description

When I want to clean some of my history I need to confirm everytime which I find annoying.

Confirmation

🧐 Proposed Solution

Option to control if you want confirmation before deleting a conversation.

📝 Additional Information

No response

Rekkertt avatar Sep 12 '24 20:09 Rekkertt

👀 @Rekkertt

Thank you for raising an issue. We will investigate into the matter and get back to you as soon as possible. Please make sure you have given us as much context as possible.
非常感谢您提交 issue。我们会尽快调查此事,并尽快回复您。 请确保您已经提供了尽可能多的背景信息。

lobehubbot avatar Sep 12 '24 20:09 lobehubbot

Hey @Rekkertt! 👋 I'm here to assist you with any bugs, questions, or contributions while you wait for a human maintainer. Let's tackle this together!

To add an option to disable the message deletion confirmation dialog, you can introduce a configuration setting that controls whether the confirmation dialog should be shown. Here is how you can modify the existing code to include this option:

  1. Add a new configuration setting in your configuration service.
  2. Modify the onClick handler for the delete action to check this setting before showing the confirmation dialog.

Here's the updated code:

import { ActionIcon, Icon } from '@lobehub/ui';
import { App, Dropdown } from 'antd';
import { createStyles } from 'antd-style';
import { ItemType } from 'antd/es/menu/interface';
import isEqual from 'fast-deep-equal';
import {
  Check,
  HardDriveDownload,
  ListTree,
  LucideCopy,
  LucidePlus,
  MoreVertical,
  Pin,
  PinOff,
  Trash,
} from 'lucide-react';
import { memo, useMemo } from 'react';
import { useTranslation } from 'react-i18next';

import { isServerMode } from '@/const/version';
import { configService } from '@/services/config';
import { useSessionStore } from '@/store/session';
import { sessionHelpers } from '@/store/session/helpers';
import { sessionGroupSelectors, sessionSelectors } from '@/store/session/selectors';
import { SessionDefaultGroup } from '@/types/session';

const useStyles = createStyles(({ css }) => ({
  modalRoot: css`
    z-index: 2000;
  `,
}));

interface ActionProps {
  group: string | undefined;
  id: string;
  openCreateGroupModal: () => void;
  setOpen: (open: boolean) => void;
}

const Actions = memo<ActionProps>(({ group, id, openCreateGroupModal, setOpen }) => {
  const { styles } = useStyles();
  const { t } = useTranslation('chat');

  const sessionCustomGroups = useSessionStore(sessionGroupSelectors.sessionGroupItems, isEqual);
  const [pin, removeSession, pinSession, duplicateSession, updateSessionGroup] = useSessionStore(
    (s) => {
      const session = sessionSelectors.getSessionById(id)(s);
      return [
        sessionHelpers.getSessionPinned(session),
        s.removeSession,
        s.pinSession,
        s.duplicateSession,
        s.updateSessionGroupId,
      ];
    },
  );

  const { modal, message } = App.useApp();

  const isDefault = group === SessionDefaultGroup.Default;
  // const hasDivider = !isDefault || Object.keys(sessionByGroup).length > 0;
const items = useMemo(
    () =>
      (
        [
          {
            icon: <Icon icon={pin ? PinOff : Pin} />,
            key: 'pin',
            label: t(pin ? 'pinOff' : 'pin'),
            onClick: () => {
              pinSession(id, !pin);
            },
          },
          {
            icon: <Icon icon={LucideCopy} />,
            key: 'duplicate',
            label: t('duplicate', { ns: 'common' }),
            onClick: ({ domEvent }) => {
              domEvent.stopPropagation();
duplicateSession(id);
            },
          },
          {
            type: 'divider',
          },
          {
            children: [
              ...sessionCustomGroups.map(({ id: groupId, name }) => ({
                icon: group === groupId ? <Icon icon={Check} /> : <div />,
                key: groupId,
                label: name,
                onClick: () => {
                  updateSessionGroup(id, groupId);
                },
              })),
              {
                icon: isDefault ? <Icon icon={Check} /> : <div />,
                key: 'defaultList',
                label: t('defaultList'),
                onClick: () => {
                  updateSessionGroup(id, SessionDefaultGroup.Default);
                },
              },
              {
                type: 'divider',
              },
              {
                icon: <Icon icon={LucidePlus} />,
                key: 'createGroup',
                label: <div>{t('sessionGroup.createGroup')}</div>,
                onClick: ({ domEvent }) => {
                  domEvent.stopPropagation();
                  openCreateGroupModal();
                },
              },
            ],
            icon: <Icon icon={ListTree} />,
            key: 'moveGroup',
            label: t('sessionGroup.moveGroup'),
          },
          {
            type: 'divider',
          },
          isServerMode
            ? undefined
            : {
                children: [
                  {
                    key: 'agent',
                    label: t('exportType.agent', { ns: 'common' }),
                    onClick: () => {
                      configService.exportSingleAgent(id);
                    },
                  },
                  {
                    key: 'agentWithMessage',
                    label: t('exportType.agentWithMessage', { ns: 'common' }),
                    onClick: () => {
                      configService.exportSingleSession(id);
                    },
                  },
                ],
icon: <Icon icon={HardDriveDownload} />,
                key: 'export',
                label: t('export', { ns: 'common' }),
              },
          {
            danger: true,
            icon: <Icon icon={Trash} />,
            key: 'delete',
            label: t('delete', { ns: 'common' }),
            onClick: ({ domEvent }) => {
              domEvent.stopPropagation();
              const showConfirmation = configService.get('showDeleteConfirmation', true);
              if (showConfirmation) {
                modal.confirm({
                  centered: true,
                  okButtonProps: { danger: true },
                  onOk: async () => {
                    await removeSession(id);
                    message.success(t('confirmRemoveSessionSuccess'));
                  },
                  rootClassName: styles.modalRoot,
                  title: t('confirmRemoveSessionItemAlert'),
                });
              } else {
                removeSession(id);
                message.success(t('confirmRemoveSessionSuccess'));
              }
            },
          },
        ] as ItemType[]
      ).filter(Boolean),
    [id, pin],
  );
return (
    <Dropdown
      arrow={false}
      menu={{
        items,
        onClick: ({ domEvent }) => {
          domEvent.stopPropagation();
        },
      }}
      onOpenChange={setOpen}
      trigger={['click']}
    >
      <ActionIcon
        icon={MoreVertical}
        size={{
          blockSize: 28,
          fontSize: 16,
        }}
      />
    </Dropdown>
  );
});

export default Actions;

In this code, configService.get('showDeleteConfirmation', true) is used to check if the confirmation dialog should be shown. If the setting is true, the confirmation dialog is displayed; otherwise, the session is deleted immediately. You will need to ensure that configService has the appropriate method to get this configuration setting [1].

To continue talking to Dosu, mention @dosu.

dosubot[bot] avatar Sep 12 '24 20:09 dosubot[bot]

Please keep this conformation, to avoid miss click.

Lostsite avatar Sep 12 '24 22:09 Lostsite

May consider temporarily turning off secondary confirmation when messages are deleted continuously.

sxjeru avatar Sep 13 '24 02:09 sxjeru

> Please keep this conformation, to avoid miss click.

I mean an extra option for those who want to disable it or something similair like sxjeru suggested.

Rekkertt avatar Sep 13 '24 08:09 Rekkertt

I perfer to support multi select and then delete

arvinxx avatar Sep 13 '24 15:09 arvinxx