Skip to content

Commit 4b0a534

Browse files
authored
Merge pull request #595 from sugarforever/revert-594-feature/component-preview
Revert "Feature/component preview"
2 parents 39c5138 + 7045763 commit 4b0a534

File tree

7 files changed

+202
-510
lines changed

7 files changed

+202
-510
lines changed

components/Chat.vue

+4-12
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ const emits = defineEmits<{
1717
// it means remove a message if `data` is null
1818
message: [data: ChatMessage | null]
1919
changeSettings: [data: ChatSessionSettings]
20-
'toggle-sidebar': []
2120
}>()
2221
2322
const { t } = useI18n()
@@ -283,9 +282,6 @@ const onPreviewRequest = (content: string) => {
283282
previewContent.value = content
284283
showPreview.value = true
285284
}
286-
287-
// Add near the top of the script section
288-
const isSessionListVisible = inject('isSessionListVisible', ref(true))
289285
</script>
290286

291287
<template>
@@ -294,10 +290,6 @@ const isSessionListVisible = inject('isSessionListVisible', ref(true))
294290
<div class="flex flex-col flex-1 min-w-0">
295291
<div class="px-4 border-b border-gray-200 dark:border-gray-700 box-border h-[57px] flex items-center">
296292
<slot name="left-menu-btn"></slot>
297-
<UIcon
298-
:name="isSessionListVisible ? 'i-heroicons-chevron-double-left' : 'i-heroicons-chevron-double-right'"
299-
class="mr-2 text-lg text-gray-500 hidden md:block cursor-pointer hover:text-primary-500"
300-
@click="$emit('toggle-sidebar')" />
301293
<ChatConfigInfo v-if="instructionInfo" icon="i-iconoir-terminal"
302294
:title="instructionInfo.name"
303295
:description="instructionInfo.instruction"
@@ -339,9 +331,9 @@ const isSessionListVisible = inject('isSessionListVisible', ref(true))
339331
</div>
340332

341333
<!-- Preview panel -->
342-
<ComponentPreview
343-
:content="previewContent"
344-
:show="showPreview"
345-
@close="showPreview = false" />
334+
<MarkdownPreview
335+
:content="previewContent"
336+
:show="showPreview"
337+
@close="showPreview = false" />
346338
</div>
347339
</template>

components/ChatMessageItem.vue

+90-141
Original file line numberDiff line numberDiff line change
@@ -1,193 +1,142 @@
11
<script lang="ts" setup>
22
import type { ChatMessage } from '~/types/chat'
3-
import { defineAsyncComponent } from 'vue'
43
54
const props = defineProps<{
6-
message: ChatMessage
7-
sending: boolean
8-
showToggleButton?: boolean
9-
isPreviewing?: boolean
5+
message: ChatMessage
6+
sending: boolean
7+
showToggleButton?: boolean
8+
isPreviewing?: boolean
109
}>()
1110
1211
const emits = defineEmits<{
13-
resend: [message: ChatMessage]
14-
remove: [message: ChatMessage]
15-
preview: [content: string]
12+
resend: [message: ChatMessage]
13+
remove: [message: ChatMessage]
14+
preview: [content: string]
1615
}>()
1716
1817
const markdown = useMarkdown()
1918
2019
const opened = ref(props.showToggleButton === true ? false : true)
2120
const isModelMessage = computed(() => props.message.role === 'assistant')
2221
const contentClass = computed(() => {
23-
return [
24-
isModelMessage.value ? 'max-w-[calc(100%-2rem)]' : 'max-w-full',
25-
props.message.type === 'error'
26-
? 'bg-red-50 dark:bg-red-800/60'
27-
: (isModelMessage.value ? 'bg-gray-50 dark:bg-gray-800' : 'bg-primary-50 dark:bg-primary-400/60'),
28-
]
22+
return [
23+
isModelMessage.value ? 'max-w-[calc(100%-2rem)]' : 'max-w-full',
24+
props.message.type === 'error'
25+
? 'bg-red-50 dark:bg-red-800/60'
26+
: (isModelMessage.value ? 'bg-gray-50 dark:bg-gray-800' : 'bg-primary-50 dark:bg-primary-400/60'),
27+
]
2928
})
3029
3130
const timeUsed = computed(() => {
32-
const endTime = props.message.type === 'loading' ? Date.now() : props.message.endTime
33-
return Number(((endTime - props.message.startTime) / 1000).toFixed(1))
31+
const endTime = props.message.type === 'loading' ? Date.now() : props.message.endTime
32+
return Number(((endTime - props.message.startTime) / 1000).toFixed(1))
3433
})
3534
3635
const modelName = computed(() => {
37-
return parseModelValue(props.message.model)
36+
return parseModelValue(props.message.model)
3837
})
3938
4039
watch(() => props.showToggleButton, (value) => {
41-
opened.value = value === true ? false : true
40+
opened.value = value === true ? false : true
4241
})
4342
4443
const showPreview = ref(false)
4544
46-
const previewComponent = ref<any>(null)
47-
const isVueComponent = ref(false)
48-
4945
const togglePreview = () => {
50-
if (!props.message.content) return
51-
52-
const vueMatch = props.message.content.match(/```vue\n([\s\S]*?)```/)
53-
if (vueMatch) {
54-
emits('preview', vueMatch[1])
55-
}
56-
}
57-
58-
const extractTemplate = (code: string) => {
59-
const templateMatch = code.match(/<template>([\s\S]*)<\/template>/)
60-
return templateMatch ? templateMatch[1] : ''
61-
}
62-
63-
const extractScript = (code: string) => {
64-
const scriptMatch = code.match(/<script.*>([\s\S]*)<\/script>/)
65-
return scriptMatch ? scriptMatch[1] : ''
66-
}
67-
68-
const extractStyles = (code: string) => {
69-
const styleMatch = code.match(/<style.*>([\s\S]*)<\/style>/)
70-
return styleMatch ? styleMatch[1] : ''
46+
emits('preview', props.message.content)
7147
}
7248
7349
const contentDisplay = computed(() => {
74-
if (props.isPreviewing && isModelMessage.value) {
75-
return isVueComponent.value ? 'component-preview' : 'preview-mode'
76-
}
77-
return props.message.type === 'loading' ? 'loading' : 'normal'
50+
if (props.isPreviewing && isModelMessage.value) {
51+
return 'preview-mode'
52+
}
53+
return props.message.type === 'loading' ? 'loading' : 'normal'
7854
})
7955
</script>
8056

8157
<template>
82-
<div class="flex flex-col my-2"
83-
:class="{ 'items-end': message.role === 'user' }">
84-
<div class="text-gray-500 dark:text-gray-400 p-1">
85-
<Icon v-if="message.role === 'user'" name="i-material-symbols-account-circle" class="text-lg" />
86-
<div v-else class="text-sm flex items-center">
87-
<UTooltip :text="modelName.family" :popper="{ placement: 'top' }">
88-
<span class="text-primary/80">{{ modelName.name }}</span>
89-
</UTooltip>
90-
<template v-if="timeUsed > 0">
91-
<span class="mx-2 text-muted/20 text-xs">|</span>
92-
<span class="text-gray-400 dark:text-gray-500 text-xs">{{ timeUsed }}s</span>
93-
</template>
94-
</div>
95-
</div>
96-
<div class="leading-6 text-sm flex items-center max-w-full message-content"
97-
:class="{ 'text-gray-400 dark:text-gray-500': message.type === 'canceled', 'flex-row-reverse': !isModelMessage }">
98-
<div class="flex border border-primary/20 rounded-lg overflow-hidden box-border"
99-
:class="contentClass">
100-
<div v-if="contentDisplay === 'loading'" class="text-xl text-primary p-3">
101-
<span class="block i-svg-spinners-3-dots-scale"></span>
102-
</div>
103-
<div v-else-if="contentDisplay === 'preview-mode'" class="p-3 flex items-center text-gray-500">
104-
<UIcon name="i-heroicons-document-text" class="mr-2" />
105-
<span>Content in preview</span>
58+
<div class="flex flex-col my-2"
59+
:class="{ 'items-end': message.role === 'user' }">
60+
<div class="text-gray-500 dark:text-gray-400 p-1">
61+
<Icon v-if="message.role === 'user'" name="i-material-symbols-account-circle" class="text-lg" />
62+
<div v-else class="text-sm flex items-center">
63+
<UTooltip :text="modelName.family" :popper="{ placement: 'top' }">
64+
<span class="text-primary/80">{{ modelName.name }}</span>
65+
</UTooltip>
66+
<template v-if="timeUsed > 0">
67+
<span class="mx-2 text-muted/20 text-xs">|</span>
68+
<span class="text-gray-400 dark:text-gray-500 text-xs">{{ timeUsed }}s</span>
69+
</template>
70+
</div>
10671
</div>
107-
<div v-else-if="contentDisplay === 'component-preview'" class="p-3 w-full">
108-
<div class="preview-container">
109-
<component :is="previewComponent" v-if="previewComponent" />
110-
</div>
72+
<div class="leading-6 text-sm flex items-center max-w-full message-content"
73+
:class="{ 'text-gray-400 dark:text-gray-500': message.type === 'canceled', 'flex-row-reverse': !isModelMessage }">
74+
<div class="flex border border-primary/20 rounded-lg overflow-hidden box-border"
75+
:class="contentClass">
76+
<div v-if="contentDisplay === 'loading'" class="text-xl text-primary p-3">
77+
<span class="block i-svg-spinners-3-dots-scale"></span>
78+
</div>
79+
<div v-else-if="contentDisplay === 'preview-mode'" class="p-3 flex items-center text-gray-500">
80+
<UIcon name="i-heroicons-document-text" class="mr-2" />
81+
<span>Content in preview</span>
82+
</div>
83+
<template v-else-if="isModelMessage">
84+
<div class="p-3 overflow-hidden">
85+
<div v-html="markdown.render(message.content || '')" class="md-body" :class="{ 'line-clamp-3 max-h-[5rem]': !opened }" />
86+
<Sources v-show="opened" :relevant_documents="message?.relevantDocs || []" />
87+
</div>
88+
<div class="flex flex-col">
89+
<MessageToggleCollapseButton v-if="showToggleButton" :opened="opened" @click="opened = !opened" />
90+
<UButton v-if="message.content"
91+
icon="i-heroicons-eye-20-solid"
92+
color="gray"
93+
variant="ghost"
94+
size="xs"
95+
class="mt-1 preview-btn"
96+
:class="{ 'text-primary-500': isPreviewing }"
97+
@click="togglePreview" />
98+
</div>
99+
</template>
100+
<pre v-else v-text="message.content" class="p-3 whitespace-break-spaces" />
101+
</div>
102+
<ChatMessageActionMore :message="message"
103+
:disabled="sending"
104+
@resend="emits('resend', message)"
105+
@remove="emits('remove', message)">
106+
<UButton :class="{ invisible: sending }" icon="i-material-symbols-more-vert" color="gray"
107+
:variant="'link'"
108+
class="action-more">
109+
</UButton>
110+
</ChatMessageActionMore>
111111
</div>
112-
<template v-else-if="isModelMessage">
113-
<div class="p-3 overflow-hidden">
114-
<div v-html="markdown.render(message.content || '')" class="md-body" :class="{ 'line-clamp-3 max-h-[5rem]': !opened }" />
115-
<Sources v-show="opened" :relevant_documents="message?.relevantDocs || []" />
116-
</div>
117-
<div class="flex flex-col">
118-
<MessageToggleCollapseButton v-if="showToggleButton" :opened="opened" @click="opened = !opened" />
119-
<UButton v-if="message.content"
120-
icon="i-heroicons-eye-20-solid"
121-
color="gray"
122-
variant="ghost"
123-
size="xs"
124-
class="mt-1 preview-btn"
125-
:class="{ 'text-primary-500': isPreviewing }"
126-
@click="togglePreview" />
127-
</div>
128-
</template>
129-
<pre v-else v-text="message.content" class="p-3 whitespace-break-spaces" />
130-
</div>
131-
<ChatMessageActionMore :message="message"
132-
:disabled="sending"
133-
@resend="emits('resend', message)"
134-
@remove="emits('remove', message)">
135-
<UButton :class="{ invisible: sending }" icon="i-material-symbols-more-vert" color="gray"
136-
:variant="'link'"
137-
class="action-more">
138-
</UButton>
139-
</ChatMessageActionMore>
140112
</div>
141-
</div>
142113
</template>
143114

144115
<style scoped lang="scss">
145116
.message-content {
146-
.action-more {
147-
transform-origin: center center;
148-
transition: all 0.3s;
149-
transform: scale(0);
150-
opacity: 0;
151-
}
152-
153-
&:hover {
154117
.action-more {
155-
transform: scale(1);
156-
opacity: 1;
118+
transform-origin: center center;
119+
transition: all 0.3s;
120+
transform: scale(0);
121+
opacity: 0;
157122
}
158-
}
159123
160-
.preview-btn {
161-
opacity: 0;
162-
transition: opacity 0.3s;
163-
}
124+
&:hover {
125+
.action-more {
126+
transform: scale(1);
127+
opacity: 1;
128+
}
129+
}
164130
165-
&:hover {
166131
.preview-btn {
167-
opacity: 1;
132+
opacity: 0;
133+
transition: opacity 0.3s;
168134
}
169-
}
170-
}
171-
172-
.preview-container {
173-
border: 1px solid var(--color-gray-200);
174-
border-radius: 0.5rem;
175-
padding: 1rem;
176-
background: var(--color-gray-50);
177-
min-height: 100px;
178135
179-
:deep() {
180-
* {
181-
margin: initial;
182-
padding: initial;
136+
&:hover {
137+
.preview-btn {
138+
opacity: 1;
139+
}
183140
}
184-
}
185-
}
186-
187-
.dark {
188-
.preview-container {
189-
border-color: var(--color-gray-700);
190-
background: var(--color-gray-800);
191-
}
192141
}
193142
</style>

0 commit comments

Comments
 (0)