ChatMessageActions.svelte 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. <script lang="ts">
  2. import { Edit, Copy, RefreshCw, Trash2, ArrowRight } from '@lucide/svelte';
  3. import {
  4. ActionButton,
  5. ChatMessageBranchingControls,
  6. DialogConfirmation
  7. } from '$lib/components/app';
  8. interface Props {
  9. role: 'user' | 'assistant';
  10. justify: 'start' | 'end';
  11. actionsPosition: 'left' | 'right';
  12. siblingInfo?: ChatMessageSiblingInfo | null;
  13. showDeleteDialog: boolean;
  14. deletionInfo: {
  15. totalCount: number;
  16. userMessages: number;
  17. assistantMessages: number;
  18. messageTypes: string[];
  19. } | null;
  20. onCopy: () => void;
  21. onEdit?: () => void;
  22. onRegenerate?: () => void;
  23. onContinue?: () => void;
  24. onDelete: () => void;
  25. onConfirmDelete: () => void;
  26. onNavigateToSibling?: (siblingId: string) => void;
  27. onShowDeleteDialogChange: (show: boolean) => void;
  28. }
  29. let {
  30. actionsPosition,
  31. deletionInfo,
  32. justify,
  33. onCopy,
  34. onEdit,
  35. onConfirmDelete,
  36. onContinue,
  37. onDelete,
  38. onNavigateToSibling,
  39. onShowDeleteDialogChange,
  40. onRegenerate,
  41. role,
  42. siblingInfo = null,
  43. showDeleteDialog
  44. }: Props = $props();
  45. function handleConfirmDelete() {
  46. onConfirmDelete();
  47. onShowDeleteDialogChange(false);
  48. }
  49. </script>
  50. <div class="relative {justify === 'start' ? 'mt-2' : ''} flex h-6 items-center justify-{justify}">
  51. <div
  52. class="absolute top-0 {actionsPosition === 'left'
  53. ? 'left-0'
  54. : 'right-0'} flex items-center gap-2 opacity-100 transition-opacity"
  55. >
  56. {#if siblingInfo && siblingInfo.totalSiblings > 1}
  57. <ChatMessageBranchingControls {siblingInfo} {onNavigateToSibling} />
  58. {/if}
  59. <div
  60. class="pointer-events-auto inset-0 flex items-center gap-1 opacity-100 transition-all duration-150"
  61. >
  62. <ActionButton icon={Copy} tooltip="Copy" onclick={onCopy} />
  63. {#if onEdit}
  64. <ActionButton icon={Edit} tooltip="Edit" onclick={onEdit} />
  65. {/if}
  66. {#if role === 'assistant' && onRegenerate}
  67. <ActionButton icon={RefreshCw} tooltip="Regenerate" onclick={onRegenerate} />
  68. {/if}
  69. {#if role === 'assistant' && onContinue}
  70. <ActionButton icon={ArrowRight} tooltip="Continue" onclick={onContinue} />
  71. {/if}
  72. <ActionButton icon={Trash2} tooltip="Delete" onclick={onDelete} />
  73. </div>
  74. </div>
  75. </div>
  76. <DialogConfirmation
  77. bind:open={showDeleteDialog}
  78. title="Delete Message"
  79. description={deletionInfo && deletionInfo.totalCount > 1
  80. ? `This will delete ${deletionInfo.totalCount} messages including: ${deletionInfo.userMessages} user message${deletionInfo.userMessages > 1 ? 's' : ''} and ${deletionInfo.assistantMessages} assistant response${deletionInfo.assistantMessages > 1 ? 's' : ''}. All messages in this branch and their responses will be permanently removed. This action cannot be undone.`
  81. : 'Are you sure you want to delete this message? This action cannot be undone.'}
  82. confirmText={deletionInfo && deletionInfo.totalCount > 1
  83. ? `Delete ${deletionInfo.totalCount} Messages`
  84. : 'Delete'}
  85. cancelText="Cancel"
  86. variant="destructive"
  87. icon={Trash2}
  88. onConfirm={handleConfirmDelete}
  89. onCancel={() => onShowDeleteDialogChange(false)}
  90. />