diff --git a/packages/app/src/components/chat/ChatHeader.vue b/packages/app/src/components/chat/ChatHeader.vue index fd333cf8..91324649 100644 --- a/packages/app/src/components/chat/ChatHeader.vue +++ b/packages/app/src/components/chat/ChatHeader.vue @@ -45,6 +45,17 @@ + + + + + + + + + + + + + Export + + Markdown (.md) + + + JSON + + + Plain text (.txt) + + + + Delete conversation + + + + + @@ -157,6 +209,7 @@ import { ref, computed, watch, nextTick } from 'vue' import { useChatStore } from '@/stores/chat' import { useAI } from '@/composables/useAI' import { useContentPanel } from '@/composables/useContentPanel' +import { downloadConversation, type ExportFormat } from '@/utils/conversation-export' defineProps<{ title: string @@ -176,6 +229,9 @@ const chatStore = useChatStore() const webSearchEnabled = computed(() => chatStore.webSearchEnabled) const showModelPicker = ref(false) const showChatList = ref(false) +const showMenu = ref(false) +const menuTriggerRef = ref(null) +const menuDropdownStyle = ref>({}) const headerRef = ref(null) const chatListTriggerRef = ref(null) const modelPickerTriggerRef = ref(null) @@ -211,8 +267,22 @@ function updateModelPickerPosition() { }) } +function updateMenuPosition() { + nextTick(() => { + const el = menuTriggerRef.value + if (el) { + const r = el.getBoundingClientRect() + menuDropdownStyle.value = { + top: `${r.bottom + 4}px`, + right: `${window.innerWidth - r.right}px`, + } + } + }) +} + watch(showChatList, (v) => { if (v) updateChatListPosition() }) watch(showModelPicker, (v) => { if (v) updateModelPickerPosition() }) +watch(showMenu, (v) => { if (v) updateMenuPosition() }) const conversationList = computed(() => chatStore.conversationList) const activeConversationId = computed(() => chatStore.activeConversationId) @@ -246,6 +316,20 @@ function openDesignSystem() { enterDesignSystemMode() showModelPicker.value = false } + +async function handleExport(format: ExportFormat) { + const conv = chatStore.activeConversation + if (!conv) return + await downloadConversation(conv, format) + showMenu.value = false +} + +function handleDelete() { + const id = chatStore.activeConversationId + if (!id) return + chatStore.deleteConversation(id) + showMenu.value = false +}
Export